aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/synth/netlists-dump.adb5
-rw-r--r--src/synth/netlists-gates.ads16
-rw-r--r--src/synth/netlists.ads52
-rw-r--r--src/synth/synth-inference.adb56
4 files changed, 108 insertions, 21 deletions
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