diff options
Diffstat (limited to 'src/synth/synth-disp_vhdl.adb')
-rw-r--r-- | src/synth/synth-disp_vhdl.adb | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/src/synth/synth-disp_vhdl.adb b/src/synth/synth-disp_vhdl.adb new file mode 100644 index 000000000..21ac11737 --- /dev/null +++ b/src/synth/synth-disp_vhdl.adb @@ -0,0 +1,231 @@ +-- Disp a netlist in vhdl using the original entity. +-- Copyright (C) 2019 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 Simple_IO; use Simple_IO; +with Types; use Types; +with Name_Table; + +with Vhdl.Prints; +with Vhdl.Ieee.Std_Logic_1164; +with Vhdl.Errors; use Vhdl.Errors; + +with Netlists.Iterators; use Netlists.Iterators; +with Netlists.Disp_Vhdl; use Netlists.Disp_Vhdl; + +package body Synth.Disp_Vhdl is + procedure Disp_Signal (Desc : Port_Desc) is + begin + Put (" signal "); + Put_Name (Desc.Name); + Put (": "); + Put_Type (Desc.W); + Put_Line (";"); + end Disp_Signal; + + procedure Disp_Ports_As_Signals (M : Module) is + begin + for I in 1 .. Get_Nbr_Inputs (M) loop + Disp_Signal (Get_Input_Desc (M, I - 1)); + end loop; + for I in 1 .. Get_Nbr_Outputs (M) loop + Disp_Signal (Get_Output_Desc (M, I - 1)); + end loop; + end Disp_Ports_As_Signals; + + procedure Disp_In_Converter + (M : Module; Idx : in out Port_Idx; Pfx : String; Ptype : Node) + is + Btype : constant Node := Get_Base_Type (Ptype); + Desc : constant Port_Desc := Get_Input_Desc (M, Idx); + begin + case Get_Kind (Btype) is + when Iir_Kind_Enumeration_Type_Definition => + if Btype = Vhdl.Ieee.Std_Logic_1164.Std_Ulogic_Type + or else Btype = Vhdl.Ieee.Std_Logic_1164.Std_Logic_Type + then + -- Nothing to do. + Put_Line (" wrap_" & Pfx & " <= " & Pfx & ";"); + Idx := Idx + 1; + else + Error_Kind ("disp_in_converter(enum)", Ptype); + end if; + when Iir_Kind_Array_Type_Definition => + if Btype = Vhdl.Ieee.Std_Logic_1164.Std_Logic_Vector_Type then + -- Nothing to do. + Put (" wrap_" & Pfx & " <= " & Pfx); + if Desc.W = 1 then + -- This is an array of length 1. A scalar is used in the + -- netlist. + Put (" (" & Pfx & "'left)"); + end if; + Put_Line (";"); + Idx := Idx + 1; + else + Error_Kind ("disp_in_converter(arr)", Ptype); + end if; + when others => + Error_Kind ("disp_in_converter", Ptype); + end case; + end Disp_In_Converter; + + procedure Disp_Out_Converter + (M : Module; Idx : in out Port_Idx; Pfx : String; Ptype : Node) + is + Btype : constant Node := Get_Base_Type (Ptype); + Desc : constant Port_Desc := Get_Output_Desc (M, Idx); + begin + case Get_Kind (Btype) is + when Iir_Kind_Enumeration_Type_Definition => + if Btype = Vhdl.Ieee.Std_Logic_1164.Std_Ulogic_Type + or else Btype = Vhdl.Ieee.Std_Logic_1164.Std_Logic_Type + then + -- Nothing to do. + Put_Line (" " & Pfx & " <= wrap_" & Pfx & ";"); + Idx := Idx + 1; + else + -- Any other enum. + Put (" " & Pfx & " <= "); + Put (Name_Table.Image (Get_Identifier + (Get_Type_Declarator (Ptype)))); + Put ("'val (to_integer(unsigned(wrap_" & Pfx & ")));"); + New_Line; + Idx := Idx + 1; + end if; + when Iir_Kind_Array_Type_Definition => + if Btype = Vhdl.Ieee.Std_Logic_1164.Std_Logic_Vector_Type then + -- Nothing to do. + Put (" " & Pfx); + if Desc.W = 1 then + -- This is an array of length 1. A scalar is used in the + -- netlist. + Put (" (" & Pfx & "'left)"); + end if; + Put_Line (" <= wrap_" & Pfx & ";"); + Idx := Idx + 1; + else + Error_Kind ("disp_out_converter(arr)", Ptype); + end if; + when others => + Error_Kind ("disp_out_converter", Ptype); + end case; + end Disp_Out_Converter; + + procedure Disp_Vhdl_Wrapper (Ent : Node; Top : Module) + is + Unit : constant Node := Get_Design_Unit (Ent); + Main : Module; + Name_Wrap : Name_Id; + begin + -- Extract the first user submodule. + Main := Get_First_Sub_Module (Top); + while Get_Id (Main) < Id_User_None loop + Main := Get_Next_Sub_Module (Main); + end loop; + + -- Disp the original design unit. + Vhdl.Prints.Disp_Vhdl (Unit); + + -- Disp sub-units (in reverse order). + declare + M : Module; + Num : Natural; + begin + Num := 0; + M := Get_Next_Sub_Module (Main); + while M /= No_Module loop + if Get_Id (M) >= Id_User_None then + Num := Num + 1; + end if; + M := Get_Next_Sub_Module (M); + end loop; + + declare + type Module_Array is array (1 .. Num) of Module; + Modules : Module_Array; + begin + Num := 0; + M := Get_Next_Sub_Module (Main); + while M /= No_Module loop + if Get_Id (M) >= Id_User_None then + Num := Num + 1; + Modules (Num) := M; + end if; + M := Get_Next_Sub_Module (M); + end loop; + + for I in reverse Modules'Range loop + Netlists.Disp_Vhdl.Disp_Vhdl (Modules (I), False); + end loop; + end; + end; + New_Line; + + -- Rename ports. + Name_Wrap := Name_Table.Get_Identifier ("wrap"); + for P of Ports_Desc (Main) loop + pragma Assert (Get_Sname_Prefix (P.Name) = No_Sname); + Set_Sname_Prefix (P.Name, New_Sname_User (Name_Wrap)); + end loop; + + Put_Line ("library ieee;"); + Put_Line ("use ieee.numeric_std.all;"); + New_Line; + Put ("architecture rtl of "); + Put (Name_Table.Image (Get_Identifier (Ent))); + Put_Line (" is"); + Disp_Ports_As_Signals (Main); + Disp_Architecture_Declarations (Main); + + Put_Line ("begin"); + -- TODO: add assert for the value of the generics. + + declare + Idx : Port_Idx; + Port : Node; + begin + Port := Get_Port_Chain (Ent); + Idx := 0; + while Port /= Null_Node loop + if Get_Mode (Port) = Iir_In_Mode then + Disp_In_Converter + (Main, Idx, + Name_Table.Image (Get_Identifier (Port)), Get_Type (Port)); + end if; + Port := Get_Chain (Port); + end loop; + pragma Assert (Idx = Get_Nbr_Inputs (Main)); + + Port := Get_Port_Chain (Ent); + Idx := 0; + while Port /= Null_Node loop + if Get_Mode (Port) = Iir_Out_Mode then + Disp_Out_Converter + (Main, Idx, + Name_Table.Image (Get_Identifier (Port)), Get_Type (Port)); + end if; + Port := Get_Chain (Port); + end loop; + pragma Assert (Idx = Get_Nbr_Outputs (Main)); + end; + + Disp_Architecture_Statements (Main); + Put_Line ("end rtl;"); + end Disp_Vhdl_Wrapper; +end Synth.Disp_Vhdl; |