aboutsummaryrefslogtreecommitdiffstats
path: root/src/synth/synthesis.adb
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2017-01-30 21:09:19 +0100
committerTristan Gingold <tgingold@free.fr>2017-01-31 20:22:08 +0100
commitbc10b035f5998d1cc9ec2aa0122ee1c24099ca05 (patch)
tree56e0e2fc8733caa1fff39a3cce9fd205b307f575 /src/synth/synthesis.adb
parent3a412a309bcea39e5c8ecd094711bc70452a1e73 (diff)
downloadghdl-bc10b035f5998d1cc9ec2aa0122ee1c24099ca05.tar.gz
ghdl-bc10b035f5998d1cc9ec2aa0122ee1c24099ca05.tar.bz2
ghdl-bc10b035f5998d1cc9ec2aa0122ee1c24099ca05.zip
Add netlist generation infrastructure.
Diffstat (limited to 'src/synth/synthesis.adb')
-rw-r--r--src/synth/synthesis.adb261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/synth/synthesis.adb b/src/synth/synthesis.adb
new file mode 100644
index 000000000..6361db001
--- /dev/null
+++ b/src/synth/synthesis.adb
@@ -0,0 +1,261 @@
+-- Synthesis.
+-- Copyright (C) 2017 Tristan Gingold
+--
+-- This file is part of GHDL.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 2 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program; if not, write to the Free Software
+-- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+-- MA 02110-1301, USA.
+
+with Types; use Types;
+with Name_Table; use Name_Table;
+
+with Netlists.Builders; use Netlists.Builders;
+
+with Iirs_Utils; use Iirs_Utils;
+with Elaboration; use Elaboration;
+
+with Synth.Environment; use Synth.Environment;
+with Synth.Values; use Synth.Values;
+with Synth.Context; use Synth.Context;
+with Synth.Types; use Synth.Types;
+with Synth.Decls; use Synth.Decls;
+with Synth.Stmts; use Synth.Stmts;
+
+with Synth.Environment.Debug;
+pragma Unreferenced (Synth.Environment.Debug);
+
+with Errorout; use Errorout;
+
+package body Synthesis is
+ function Mode_To_Port_Kind (Mode : Iir_Mode) return Port_Kind is
+ begin
+ case Mode is
+ when Iir_In_Mode =>
+ return Port_In;
+ when Iir_Buffer_Mode
+ | Iir_Out_Mode
+ | Iir_Inout_Mode =>
+ return Port_Out;
+ when Iir_Linkage_Mode
+ | Iir_Unknown_Mode =>
+ raise Synth_Error;
+ end case;
+ end Mode_To_Port_Kind;
+
+ function Get_Nbr_Wire (Val : Value_Acc) return Uns32 is
+ begin
+ case Val.Kind is
+ when Value_Wire =>
+ return 1;
+ when others =>
+ raise Internal_Error; -- TODO
+ end case;
+ end Get_Nbr_Wire;
+
+ procedure Make_Port_Desc (Val : Value_Acc;
+ Name : Sname;
+ Wd : Width;
+ Ports : in out Port_Desc_Array;
+ Idx : in out Port_Nbr;
+ Dir : Port_Kind)
+ is
+ begin
+ case Val.Kind is
+ when Value_Wire =>
+ Idx := Idx + 1;
+ Ports (Idx) := (Name => Name,
+ W => Wd,
+ Dir => Dir,
+ Left | Right => 0);
+ when others =>
+ raise Internal_Error; -- TODO
+ end case;
+ end Make_Port_Desc;
+
+ procedure Make_Port_Desc (Syn_Inst : Synth_Instance_Acc;
+ Inter : Iir;
+ Ports : in out Port_Desc_Array;
+ Idx : in out Port_Nbr;
+ Dir : Port_Kind)
+ is
+ Val : constant Value_Acc := Get_Value (Syn_Inst, Inter);
+ Wd : constant Width := Get_Width (Syn_Inst, Get_Type (Inter));
+ Name : Sname;
+ begin
+ Name := New_Sname_User (Get_Identifier (Inter));
+ Make_Port_Desc (Val, Name, Wd, Ports, Idx, Dir);
+ end Make_Port_Desc;
+
+ procedure Create_Input_Wire
+ (Self_Inst : Instance; Idx : in out Port_Idx; Val : Value_Acc) is
+ begin
+ case Val.Kind is
+ when Value_Wire =>
+ Wire_Id_Table.Table (Val.W).Gate := Get_Output (Self_Inst, Idx);
+ Idx := Idx + 1;
+ when others =>
+ raise Internal_Error;
+ end case;
+ end Create_Input_Wire;
+
+ procedure Create_Output_Wire
+ (Self_Inst : Instance; Idx : in out Port_Idx; Val : Value_Acc)
+ is
+ Value : Net;
+ Inp : Input;
+ W : Width;
+ begin
+ case Val.Kind is
+ when Value_Wire =>
+ -- Create a gate for the output, so that it could be read.
+ W := Get_Output_Desc (Get_Module (Self_Inst), Idx).W;
+ Value := Build_Output (Build_Context, W);
+ Inp := Get_Input (Self_Inst, Idx);
+ Connect (Inp, Value);
+ Wire_Id_Table.Table (Val.W).Gate := Value;
+ Idx := Idx + 1;
+ when others =>
+ raise Internal_Error;
+ end case;
+ end Create_Output_Wire;
+
+ function Synth_Entity
+ (Parent : Module; Arch : Iir; Sim_Inst : Block_Instance_Acc)
+ return Synth_Instance_Acc
+ is
+ Entity : constant Iir := Get_Entity (Arch);
+ Syn_Inst : Synth_Instance_Acc;
+ Self_Inst : Instance;
+ Inter : Iir;
+ Nbr_Inputs : Port_Nbr;
+ Nbr_Outputs : Port_Nbr;
+ Num : Uns32;
+ begin
+ Syn_Inst := Make_Instance (Sim_Inst);
+ Syn_Inst.Name := New_Sname_User (Get_Identifier (Entity));
+
+ -- Allocate values and count inputs and outputs
+ Inter := Get_Port_Chain (Entity);
+ Nbr_Inputs := 0;
+ Nbr_Outputs := 0;
+ while Is_Valid (Inter) loop
+ case Mode_To_Port_Kind (Get_Mode (Inter)) is
+ when Port_In =>
+ Make_Object (Syn_Inst, Wire_Input, Inter);
+ Num := Get_Nbr_Wire (Get_Value (Syn_Inst, Inter));
+ Nbr_Inputs := Nbr_Inputs + Port_Nbr (Num);
+ when Port_Out
+ | Port_Inout =>
+ Make_Object (Syn_Inst, Wire_Output, Inter);
+ Num := Get_Nbr_Wire (Get_Value (Syn_Inst, Inter));
+ Nbr_Outputs := Nbr_Outputs + Port_Nbr (Num);
+ end case;
+ Inter := Get_Chain (Inter);
+ end loop;
+
+ -- Declare module.
+ Syn_Inst.M :=
+ New_User_Module (Parent, New_Sname_User (Get_Identifier (Entity)),
+ Id_User_None, Nbr_Inputs, Nbr_Outputs, 0);
+
+ -- Add ports to module.
+ declare
+ Inports : Port_Desc_Array (1 .. Nbr_Inputs);
+ Outports : Port_Desc_Array (1 .. Nbr_Outputs);
+ begin
+ Inter := Get_Port_Chain (Entity);
+ Nbr_Inputs := 0;
+ Nbr_Outputs := 0;
+ while Is_Valid (Inter) loop
+ case Mode_To_Port_Kind (Get_Mode (Inter)) is
+ when Port_In =>
+ Make_Port_Desc
+ (Syn_Inst, Inter, Inports, Nbr_Inputs, Port_In);
+ when Port_Out
+ | Port_Inout =>
+ Make_Port_Desc
+ (Syn_Inst, Inter, Outports, Nbr_Outputs, Port_Out);
+ end case;
+ Inter := Get_Chain (Inter);
+ end loop;
+ pragma Assert (Nbr_Inputs = Inports'Last);
+ pragma Assert (Nbr_Outputs = Outports'Last);
+ Set_Port_Desc (Syn_Inst.M, Inports, Outports);
+ end;
+
+ Self_Inst := Create_Self_Instance (Syn_Inst.M);
+ Set_Parent (Build_Context, Syn_Inst.M);
+
+ -- Create wires for inputs and outputs.
+ Inter := Get_Port_Chain (Entity);
+ Nbr_Inputs := 0;
+ Nbr_Outputs := 0;
+ while Is_Valid (Inter) loop
+ case Mode_To_Port_Kind (Get_Mode (Inter)) is
+ when Port_In =>
+ Create_Input_Wire
+ (Self_Inst, Nbr_Inputs, Get_Value (Syn_Inst, Inter));
+ when Port_Out
+ | Port_Inout =>
+ Create_Output_Wire
+ (Self_Inst, Nbr_Outputs, Get_Value (Syn_Inst, Inter));
+ end case;
+ Inter := Get_Chain (Inter);
+ end loop;
+
+ Synth_Declarations (Syn_Inst, Get_Declaration_Chain (Entity));
+ Synth_Statements (Syn_Inst, Get_Concurrent_Statement_Chain (Entity));
+
+ Synth_Declarations (Syn_Inst, Get_Declaration_Chain (Arch));
+ Synth_Statements (Syn_Inst, Get_Concurrent_Statement_Chain (Arch));
+
+ Remove_Free_Instances (Syn_Inst.M);
+
+ return Syn_Inst;
+ end Synth_Entity;
+
+ function Synth_Design (Design : Iir) return Module
+ is
+ Unit : constant Iir := Get_Library_Unit (Design);
+ Arch : Iir;
+
+ Des : Module;
+ Syn_Inst : Synth_Instance_Acc;
+ begin
+ -- Extract architecture from design.
+ case Get_Kind (Unit) is
+ when Iir_Kind_Architecture_Body =>
+ Arch := Unit;
+ when Iir_Kind_Configuration_Declaration =>
+ Arch := Get_Named_Entity
+ (Get_Block_Specification (Get_Block_Configuration (Unit)));
+ when others =>
+ Error_Kind ("synth_design", Unit);
+ end case;
+
+ Instance_Map := new Instance_Map_Array (0 .. Nbr_Block_Instances);
+
+ Des := New_Design (New_Sname_Artificial (Get_Identifier ("top")));
+ Build_Context := Build_Builders (Des);
+ Syn_Inst := Synth_Entity (Des, Arch, Top_Instance);
+
+ if Errorout.Nbr_Errors > 0 then
+ raise Compilation_Error;
+ end if;
+
+ pragma Unreferenced (Syn_Inst);
+ return Des;
+ end Synth_Design;
+end Synthesis;