From 1a7a8ac61228917e81d1a27222f8faa0b35385c0 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Tue, 16 Apr 2019 19:03:15 +0200 Subject: synth: add comments. --- src/synth/netlists-dump.adb | 5 ++++ src/synth/netlists-gates.ads | 16 ++++++++++--- src/synth/netlists.ads | 52 ++++++++++++++++++++++++++-------------- src/synth/synth-inference.adb | 56 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/synth/netlists-dump.adb b/src/synth/netlists-dump.adb index 7db8f850e..16818bada 100644 --- a/src/synth/netlists-dump.adb +++ b/src/synth/netlists-dump.adb @@ -189,6 +189,7 @@ package body Netlists.Dump is procedure Dump_Module_Header (M : Module; Indent : Natural := 0) is begin + -- Module id and name. Put_Indent (Indent); Put ("module ("); Put_Trim (Module'Image (M)); @@ -196,6 +197,7 @@ package body Netlists.Dump is Dump_Name (Get_Name (M)); New_Line; + -- Parameters. for P of Params_Desc (M) loop Put_Indent (Indent + 1); Put ("parameter"); @@ -211,6 +213,7 @@ package body Netlists.Dump is New_Line; end loop; + -- Ports. for P of Ports_Desc (M) loop Put_Indent (Indent + 1); case P.Dir is @@ -460,6 +463,7 @@ package body Netlists.Dump is begin Dump_Module_Header (M, Indent); + -- Submodules. for S of Sub_Modules (M) loop if Get_Id (S) >= Id_User_None then Disp_Module (S, Indent + 1); @@ -472,6 +476,7 @@ package body Netlists.Dump is end if; end loop; + -- Assignments to outputs. declare Self : constant Instance := Get_Self_Instance (M); begin diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads index 1f03b0ce9..2e1dd0e75 100644 --- a/src/synth/netlists-gates.ads +++ b/src/synth/netlists-gates.ads @@ -75,10 +75,20 @@ package Netlists.Gates is Id_Output : constant Module_Id := 31; -- Note: initial values must be constant nets. + -- + -- A simple D flip-flop. The D input is stored on a rising edge of CLK. + -- Q is the output. For falling edge dff, use a NOT gate on the CLK + -- input. Id_Dff : constant Module_Id := 32; - Id_Adff : constant Module_Id := 33; -- Async reset - Id_Idff : constant Module_Id := 34; -- With initial value - Id_Iadff : constant Module_Id := 35; -- With initial value, async reset + -- A DFF with an asynchronous reset. Note that the asynchronous reset + -- has priority over the clock. When RST is asserted, the value is + -- set to RVAL. + Id_Adff : constant Module_Id := 33; + -- A simple DFF with an initial value (must be constant). This is + -- for FPGAs. + Id_Idff : constant Module_Id := 34; + -- A DFF with an asynchronous reset and an initial value. + Id_Iadff : constant Module_Id := 35; -- Width change: truncate or extend. Sign is know in order to possibly -- detect loss of value. diff --git a/src/synth/netlists.ads b/src/synth/netlists.ads index 368051b9c..80a90e7b1 100644 --- a/src/synth/netlists.ads +++ b/src/synth/netlists.ads @@ -56,15 +56,45 @@ package Netlists is function Get_Sname_Version (Name : Sname) return Uns32; function Get_Sname_Num (Name : Sname) return Uns32; - type Net is private; - No_Net : constant Net; - + -- Module. + -- + -- A module represent an uninstantiated netlist. It is composed of nets + -- and instances. + -- + -- From the outside, a module has ports (inputs and outputs), and + -- optionally parameters. A module must have at least one port. Both + -- ports and parameters have names. + -- + -- From a module, you can get the list of ports, and the list of instances. + -- Instances have names. + -- + -- In a module, there is a special instance (the self one) one that + -- represent the ports of the module itself, but with the opposite + -- direction. Using this trick, there is no difference between ports of + -- instances and ports of the module itself. + -- + -- In some cases, you also want to read an output port. This is + -- not possible in this model, so just add an 'output' gate that + -- is a nop but provides a net. + -- + -- Some modules are predefined and therefore have no inner description. + -- These are the well known elementary gates. type Module is private; No_Module : constant Module; + -- An instance is an instantiated module within a module. It is + -- connected. type Instance is private; No_Instance : constant Instance; + -- A net is an output of a gate or a sub-circuit. A net can be connected + -- to several inputs. + type Net is private; + No_Net : constant Net; + + type Input is private; + No_Input : constant Input; + -- Witdh of a net, ie number of bits. -- No_Width (value 0) is reserved to mean unknown. This is allowed only to -- describe the width of predefined gates (like and) so that the same @@ -139,18 +169,7 @@ package Netlists is type Param_Desc_Array is array (Param_Idx range <>) of Param_Desc; - -- Module. - -- - -- A module represent an uninstantiated netlist. It is composed of nets - -- and instances - -- - -- From the outside, a module has ports (inputs and outputs), and - -- optionally parameters. A module must have at least one port. - -- - -- In a module, there is a special instance (the self one) one that - -- represent the ports of the module itself, but with the opposite - -- direction. Using this trick, there is no difference between ports of - -- instances and ports of the module itself. + -- Subprograms for modules. function New_Design (Name : Sname) return Module; function New_User_Module (Parent : Module; Name : Sname; @@ -191,9 +210,6 @@ package Netlists is function Get_First_Sub_Module (M : Module) return Module; function Get_Next_Sub_Module (M : Module) return Module; - type Input is private; - No_Input : constant Input; - -- Instance function New_Instance (Parent : Module; M : Module; Name : Sname) return Instance; diff --git a/src/synth/synth-inference.adb b/src/synth/synth-inference.adb index 898d1ad51..1a7b92a35 100644 --- a/src/synth/synth-inference.adb +++ b/src/synth/synth-inference.adb @@ -24,6 +24,53 @@ with Netlists.Gates_Ports; use Netlists.Gates_Ports; with Types; use Types; package body Synth.Inference is + -- DFF inference. + -- As an initial implementation, the following 'styles' must be + -- supported: + -- Note: rising_edge is any clock_edge; '<=' can be ':='. + -- + -- 1) + -- if rising_edge(clk) then + -- r <= x; + -- end if; + -- + -- 2) + -- if rst = '0' then + -- r <= x; + -- elsif rising_edge (clk) then + -- r <= y; + -- end if; + -- + -- 3) + -- wait until rising_edge(clk); + -- r <= x; + -- Which is equivalent to 1) when the wait statement is the only and first + -- statement, as it can be converted to an if statement. + -- + -- Netlist derived from 1) + -- +------+ + -- | | + -- | /| | + -- | |0+-+ + -- Q --+--+ | + -- |1+--- D + -- \| + -- CLK + -- This is a memorizing element as there is a loop, the value is changed + -- to D on a rising edge of the clock. + -- + -- Netlist derived from 2) + -- +------------+ + -- | /| | + -- | /| |0+-+ + -- | |0+---+ | + -- Q --+--+ | |1+----- D + -- |1+-+ \| + -- \| | CLK + -- RST +--------- '0' + -- This is a memorizing element as there is a loop. It is an asynchronous + -- reset as Q is forced to '0' when RST is asserted. + type Mux_Info_Type is record Mux : Instance; Chain : Port_Nbr; @@ -31,6 +78,9 @@ package body Synth.Inference is type Mux_Info_Arr is array (Natural range <>) of Mux_Info_Type; + -- Find the longest chain of mux starting from VAL with a final input + -- of PREV_VAL. Such a chain means this is a memorising element. + -- RES is the last mux in the chain, DIST the number of mux in the chain. procedure Find_Longest_Loop (Val : Net; Prev_Val : Net; Res : out Instance; Dist : out Integer) is @@ -143,11 +193,16 @@ package body Synth.Inference is Mux : Instance; O : Net; begin + -- Start with the last mux. Mux := Last_Mux; for I in reverse Mux_Info'Range loop + -- The chain of mux consists only of muxes! pragma Assert (Get_Id (Mux) = Id_Mux2); + Mux_Info (I) := (Mux => Mux, Chain => 0); exit when I = Mux_Info'First; + + -- The next mux is connected to the output. O := Get_Output (Mux, 0); pragma Assert (Has_One_Connection (O)); Mux := Get_Parent (Get_First_Sink (O)); @@ -180,6 +235,7 @@ package body Synth.Inference is raise Internal_Error; else -- Set or reset. + -- The value must be a constant. raise Internal_Error; end if; else -- cgit v1.2.3