aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog
Commit message (Collapse)AuthorAgeFilesLines
...
* Removed compatbility.{h,cc}: Not using open_memstream/fmemopen anymoreClifford Wolf2014-08-231-4/+1
|
* Changed frontend-api from FILE to std::istreamClifford Wolf2014-08-235-22/+30
|
* Added support for non-standard <plugin>:<c_name> DPI syntaxClifford Wolf2014-08-221-0/+12
|
* Added support for DPI function with different names in C and VerilogClifford Wolf2014-08-212-5/+16
|
* Added Verilog/AST support for DPI functions (dpi_call() still unimplemented)Clifford Wolf2014-08-212-1/+54
|
* Added support for global tasks and functionsClifford Wolf2014-08-212-15/+23
|
* Added "via_celltype" attribute on task/funcClifford Wolf2014-08-181-12/+14
|
* Fixed line numbers when using here-doc macrosClifford Wolf2014-08-141-4/+9
|
* Added support for non-standard """ macro bodiesClifford Wolf2014-08-131-1/+12
|
* Also allow "module foobar(input foo, output bar, ...);" syntaxClifford Wolf2014-08-071-3/+5
|
* Added AST_MULTIRANGE (arrays with more than 1 dimension)Clifford Wolf2014-08-061-4/+18
|
* Improved scope resolution of local regs in Verilog+AST frontendClifford Wolf2014-08-051-2/+1
|
* Added support for non-standard "module mod_name(...);" syntaxClifford Wolf2014-08-041-1/+7
|
* Moved some stuff to kernel/yosys.{h,cc}, using Yosys:: namespaceClifford Wolf2014-07-316-3/+24
|
* Fixed counting verilog line numbers for "// synopsys translate_off" sectionsClifford Wolf2014-07-302-4/+4
|
* Fixed Verilog pre-processor for files with no trailing newlineClifford Wolf2014-07-291-1/+1
|
* Using log_assert() instead of assert()Clifford Wolf2014-07-283-5/+2
|
* Added "make PRETTY=1"Clifford Wolf2014-07-241-3/+3
|
* fixed parsing of constant with comment between size and valueClifford Wolf2014-07-021-0/+7
|
* Fixed parsing of TOK_INTEGER (implies TOK_SIGNED)Clifford Wolf2014-06-161-5/+11
|
* Improved parsing of large integer constantsClifford Wolf2014-06-151-11/+28
|
* Added handling of real-valued parameters/localparamsClifford Wolf2014-06-142-7/+15
|
* Added Verilog lexer and parser support for real valuesClifford Wolf2014-06-132-3/+24
|
* Added read_verilog -sv options, added support for bit, logic,Clifford Wolf2014-06-124-3/+37
| | | | allways_ff, always_comb, and always_latch
* Add support for cell arraysClifford Wolf2014-06-071-0/+7
|
* made the generate..endgenrate keywords optionalClifford Wolf2014-06-061-4/+8
|
* added while and repeat support to verilog parserClifford Wolf2014-06-062-1/+29
|
* Improved error message for options after front-end filename argumentsClifford Wolf2014-06-041-1/+1
|
* Fixed clang -Wdeprecated-register warningsClifford Wolf2014-04-201-0/+5
|
* Replaced depricated %name-prefix= bison directiveClifford Wolf2014-04-201-1/+1
|
* Merged OSX fixes from Siesh1oo with some modificationsClifford Wolf2014-03-131-0/+1
|
* Added support for `line compiler directiveClifford Wolf2014-03-111-0/+11
|
* Added Verilog support for "`default_nettype none"Clifford Wolf2014-02-175-2/+18
|
* Added a warning note about error reporting to read_verilog help messageClifford Wolf2014-02-161-0/+5
|
* Implemented read_verilog -deferClifford Wolf2014-02-131-1/+11
|
* Added support for functions returning integerClifford Wolf2014-02-121-2/+12
|
* Added read_verilog -setattrClifford Wolf2014-02-051-0/+15
|
* Added support for blanks after -I and -D in read_verilogClifford Wolf2014-02-021-7/+20
|
* Added constant size expression support of sized constantsClifford Wolf2014-02-011-0/+22
|
* Added read_verilog -icells optionClifford Wolf2014-01-291-1/+9
|
* Fixed handling of unsized constants in verilog frontendClifford Wolf2014-01-241-2/+2
|
* Added Verilog parser support for assertsClifford Wolf2014-01-192-3/+10
|
* Fixed parsing of verilog macros at end of lineClifford Wolf2014-01-181-1/+1
|
* Added verilog_defaults commandClifford Wolf2014-01-171-0/+66
|
* Fixed parsing of non-arg macro calls followed by "("Clifford Wolf2013-12-271-1/+7
|
* Fixed parsing of macros with no arguments and expansion text starting with "("Clifford Wolf2013-12-271-1/+2
|
* Added proper === and !== support in constant expressionsClifford Wolf2013-12-272-3/+11
|
* Added elsif preproc supportClifford Wolf2013-12-181-1/+14
|
* Added support for macro argumentsClifford Wolf2013-12-181-23/+75
|
* Added AstNode::mkconst_str APIClifford Wolf2013-12-051-12/+1
|
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
--  Binary file handling.
--  Copyright (C) 2006 Tristan Gingold
--
--  GHDL 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, or (at your option) any later
--  version.
--
--  GHDL 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 GCC; see the file COPYING.  If not, write to the Free
--  Software Foundation, 59 Temple Place - Suite 330, Boston, MA
--  02111-1307, USA.
with System.Storage_Elements;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Characters.Latin_1;
with Hex_Images; use Hex_Images;
with Disassemble;

package body Binary_File is
   Cur_Sect : Section_Acc := null;

   HT : Character renames Ada.Characters.Latin_1.HT;

   --  Resize a section to SIZE bytes.
   procedure Resize (Sect : Section_Acc; Size : Pc_Type) is
   begin
      Sect.Data_Max := Size;
      Memsegs.Resize (Sect.Seg, Natural (Size));
      Sect.Data := To_Byte_Array_Acc (Memsegs.Get_Address (Sect.Seg));
   end Resize;

   function Get_Scope (Sym : Symbol) return Symbol_Scope is
   begin
      return Symbols.Table (Sym).Scope;
   end Get_Scope;

   procedure Set_Scope (Sym : Symbol; Scope : Symbol_Scope) is
   begin
      Symbols.Table (Sym).Scope := Scope;
   end Set_Scope;

   function Get_Section (Sym : Symbol) return Section_Acc is
   begin
      return Symbols.Table (Sym).Section;
   end Get_Section;

   procedure Set_Section (Sym : Symbol; Sect : Section_Acc) is
   begin
      Symbols.Table (Sym).Section := Sect;
   end Set_Section;

   function Get_Number (Sym : Symbol) return Natural is
   begin
      return Symbols.Table (Sym).Number;
   end Get_Number;

   procedure Set_Number (Sym : Symbol; Num : Natural) is
   begin
      Symbols.Table (Sym).Number := Num;
   end Set_Number;

   function Get_Relocs (Sym : Symbol) return Reloc_Acc is
   begin
      return Symbols.Table (Sym).Relocs;
   end Get_Relocs;

   procedure Set_Relocs (Sym : Symbol; Reloc : Reloc_Acc) is
   begin
      Symbols.Table (Sym).Relocs := Reloc;
   end Set_Relocs;

   function Get_Name (Sym : Symbol) return O_Ident is
   begin
      return Symbols.Table (Sym).Name;
   end Get_Name;

   function Get_Used (Sym : Symbol) return Boolean is
   begin
      return Symbols.Table (Sym).Used;
   end Get_Used;

   procedure Set_Used (Sym : Symbol; Val : Boolean) is
   begin
      Symbols.Table (Sym).Used := Val;
   end Set_Used;

   function Get_Symbol_Value (Sym : Symbol) return Pc_Type is
   begin
      return Symbols.Table (Sym).Value;
   end Get_Symbol_Value;

   procedure Set_Symbol_Value (Sym : Symbol; Val : Pc_Type) is
   begin
      Symbols.Table (Sym).Value := Val;
   end Set_Symbol_Value;

   function S_Defined (Sym : Symbol) return Boolean is
   begin
      return Get_Scope (Sym) /= Sym_Undef;
   end S_Defined;
   pragma Unreferenced (S_Defined);

   function S_Local (Sym : Symbol) return Boolean is
   begin
      return Get_Scope (Sym) = Sym_Local;
   end S_Local;

   function Is_Symbol_Code (Sym : Symbol) return Boolean is
   begin
      return Symbols.Table (Sym).Code;
   end Is_Symbol_Code;

   procedure Create_Section (Sect : out Section_Acc;
                             Name : String; Flags : Section_Flags)
   is
   begin
      Sect := new Section_Type'(Next => null,
                                Flags => Flags,
                                Name => new String'(Name),
                                Link => null,
                                Align => 2,
                                Esize => 0,
                                Pc => 0,
                                Insn_Pc => 0,
                                Data => null,
                                Data_Max => 0,
                                First_Reloc => null,
                                Last_Reloc => null,
                                Nbr_Relocs => 0,
                                Number => 0,
                                Seg => Memsegs.Create,
                                Vaddr => 0);
      if (Flags and Section_Zero) = 0 then
         --  Allocate memory for the segment, unless BSS.
         Resize (Sect, 8192);
      end if;
      if (Flags and Section_Strtab) /= 0 then
         Sect.Align := 0;
      end if;
      if Section_Chain = null then
         Section_Chain := Sect;
      else
         Section_Last.Next := Sect;
      end if;
      Section_Last := Sect;
      Nbr_Sections := Nbr_Sections + 1;
   end Create_Section;

   procedure Sect_Prealloc (Sect : Section_Acc; L : Pc_Type)
   is
      New_Max : Pc_Type;
   begin
      if Sect.Pc + L < Sect.Data_Max then
         return;
      end if;
      New_Max := Sect.Data_Max;
      loop
         New_Max := New_Max * 2;
         exit when Sect.Pc + L < New_Max;
      end loop;
      Resize (Sect, New_Max);
   end Sect_Prealloc;

   procedure Merge_Section (Dest : Section_Acc; Src : Section_Acc)
   is
      Rel : Reloc_Acc;
   begin
      --  Sanity checks.
      if Src = null or else Dest = Src then
         raise Program_Error;
      end if;

      Rel := Src.First_Reloc;

      if Rel /= null then
         --  Move internal relocs.
         --  Note: external relocs are not modified, so they can still refer
         --  to this SRC section.
         if Dest.Last_Reloc = null then
            Dest.First_Reloc := Rel;
            Dest.Last_Reloc := Rel;
         else
            Dest.Last_Reloc.Sect_Next := Rel;
            Dest.Last_Reloc := Rel;
         end if;
         Dest.Nbr_Relocs := Dest.Nbr_Relocs + Src.Nbr_Relocs;

         --  Reloc reloc, since the pc has changed.
         while Rel /= null loop
            Rel.Addr := Rel.Addr + Dest.Pc;
            Rel := Rel.Sect_Next;
         end loop;
      end if;

      if Src.Pc > 0 then
         --  Alignment is assumed to be compatible...
         Sect_Prealloc (Dest, Src.Pc);
         Dest.Data (Dest.Pc .. Dest.Pc + Src.Pc - 1) :=
           Src.Data (0 .. Src.Pc - 1);
         Dest.Pc := Dest.Pc + Src.Pc;
      end if;

      Memsegs.Delete (Src.Seg);
      Src.Pc := 0;
      Src.Data_Max := 0;
      Src.Data := null;
      Src.First_Reloc := null;
      Src.Last_Reloc := null;
      Src.Nbr_Relocs := 0;

      --  Remove from section_chain.
      if Section_Chain = Src then
         Section_Chain := Src.Next;
      else
         declare
            Sect : Section_Acc;
         begin
            Sect := Section_Chain;
            while Sect.Next /= Src loop
               Sect := Sect.Next;
            end loop;
            Sect.Next := Src.Next;
            if Section_Last = Src then
               Section_Last := Sect;
            end if;
         end;
      end if;
      Nbr_Sections := Nbr_Sections - 1;
   end Merge_Section;

   procedure Set_Section_Info (Sect : Section_Acc;
                               Link : Section_Acc;
                               Align : Natural;
                               Esize : Natural)
   is
   begin
      Sect.Link := Link;
      Sect.Align := Align;
      Sect.Esize := Esize;
   end Set_Section_Info;

   procedure Set_Current_Section (Sect : Section_Acc) is
   begin
      --  If the current section does not change, this is a no-op.
      if Cur_Sect = Sect then
         return;
      end if;

      if Dump_Asm then
         Put_Line (HT & ".section """ & Sect.Name.all & """");
      end if;
      Cur_Sect := Sect;
   end Set_Current_Section;

   function Get_Current_Pc return Pc_Type is
   begin
      return Cur_Sect.Pc;
   end Get_Current_Pc;

   function Get_Pc (Sect : Section_Acc) return Pc_Type is
   begin
      return Sect.Pc;
   end Get_Pc;

   procedure Prealloc (L : Pc_Type) is
   begin
      Sect_Prealloc (Cur_Sect, L);
   end Prealloc;

   --  Reloc to be adjusted at end_insn.
   Pcrel_Reloc : Reloc_Acc := null;

   procedure Start_Insn is
   begin
      --  Check there is enough memory for the next instruction.
      Sect_Prealloc (Cur_Sect, 16);
      if Cur_Sect.Insn_Pc /= 0 then
         --  end_insn was not called.
         raise Program_Error;
      end if;
      Cur_Sect.Insn_Pc := Cur_Sect.Pc;
   end Start_Insn;

   procedure Get_Symbol_At_Addr (Addr : System.Address;
                                 Line : in out String;
                                 Line_Len : in out Natural)
   is
      use System;
      use System.Storage_Elements;
      Off : Pc_Type;
      Reloc : Reloc_Acc;
   begin
      --  Check if addr is in the current section.
      if Addr < Cur_Sect.Data (0)'Address
        or else Addr > Cur_Sect.Data (Cur_Sect.Pc)'Address
      then
         raise Program_Error;
         --return;
      end if;
      Off := Pc_Type
        (To_Integer (Addr) - To_Integer (Cur_Sect.Data (0)'Address));

      --  Find a relocation at OFF.
      Reloc := Cur_Sect.First_Reloc;
      while Reloc /= null loop
         if Reloc.Addr = Off then
            declare
               Str : constant String := Get_Symbol_Name (Reloc.Sym);
            begin
               Line (Line'First .. Line'First + Str'Length - 1) := Str;
               Line_Len := Line_Len + Str'Length;
               return;
            end;
         end if;
         Reloc := Reloc.Sect_Next;
      end loop;
   end Get_Symbol_At_Addr;

   procedure End_Insn
   is
      Str : String (1 .. 256);
      Len : Natural;
      Insn_Len : Natural;
   begin
      if Pcrel_Reloc /= null then
         Pcrel_Reloc.Neg_Addend := Cur_Sect.Pc - Pcrel_Reloc.Addr;
         Pcrel_Reloc := null;
      end if;

      --if Insn_Pc = 0 then
      --   --  start_insn was not called.
      --   raise Program_Error;
      --end if;
      if Debug_Hex then
         Put (HT);
         Put ('#');
         for I in Cur_Sect.Insn_Pc .. Cur_Sect.Pc - 1 loop
            Put (' ');
            Put (Hex_Image (Unsigned_8 (Cur_Sect.Data (I))));
         end loop;
         New_Line;
      end if;

      if Dump_Asm then
         Disassemble.Disassemble_Insn
           (Cur_Sect.Data (Cur_Sect.Insn_Pc)'Address,
            Unsigned_32 (Cur_Sect.Insn_Pc),
            Str, Len, Insn_Len,
            Get_Symbol_At_Addr'Access);
         Put (HT);
         Put_Line (Str (1 .. Len));
      end if;
      --if Natural (Cur_Pc - Insn_Pc) /= Insn_Len then
      --   raise Program_Error;
      --end if;
      Cur_Sect.Insn_Pc := 0;
   end End_Insn;

   procedure Gen_8 (B : Byte) is
   begin
      Cur_Sect.Data (Cur_Sect.Pc) := B;
      Cur_Sect.Pc := Cur_Sect.Pc + 1;
   end Gen_8;

   procedure Gen_8 (B0, B1 : Byte) is
   begin
      Cur_Sect.Data (Cur_Sect.Pc + 0) := B0;
      Cur_Sect.Data (Cur_Sect.Pc + 1) := B1;
      Cur_Sect.Pc := Cur_Sect.Pc + 2;
   end Gen_8;

   procedure Write_8 (Sect : Section_Acc; Pc : Pc_Type; V : Unsigned_8) is
   begin
      Sect.Data (Pc) := Byte (V);
   end Write_8;

   procedure Write_16 (Sect : Section_Acc; Pc : Pc_Type; B : Unsigned_32)
   is
      subtype B2 is Byte_Array_Base (0 .. 1);
      function To_B2 is new Ada.Unchecked_Conversion
        (Source => Unsigned_16, Target => B2);
   begin
      Sect.Data (Pc + 0 .. Pc + 1) := To_B2 (Unsigned_16 (B));
   end Write_16;

   procedure Write_32 (Sect : Section_Acc; Pc : Pc_Type; B : Unsigned_32)
   is
      subtype B4 is Byte_Array_Base (0 .. 3);
      function To_B4 is new Ada.Unchecked_Conversion
        (Source => Unsigned_32, Target => B4);
   begin
      Sect.Data (Pc + 0 .. Pc + 3) := To_B4 (B);
   end Write_32;

   procedure Write_64 (Sect : Section_Acc; Pc : Pc_Type; B : Unsigned_64)
   is
      subtype B8 is Byte_Array_Base (0 .. 7);
      function To_B8 is new Ada.Unchecked_Conversion
        (Source => Unsigned_64, Target => B8);
   begin
      Sect.Data (Pc + 0 .. Pc + 7) := To_B8 (B);
   end Write_64;

   procedure Write_Addr (Sect : Section_Acc; Pc : Pc_Type; B : Pc_Type)
   is
      subtype BPC is Byte_Array_Base (0 .. Pc_Type_Sizeof - 1);
      function To_BPC is new Ada.Unchecked_Conversion
        (Source => Pc_Type, Target => BPC);
   begin
      Sect.Data (Pc + 0 .. Pc + Pc_Type_Sizeof - 1) := To_BPC (B);
   end Write_Addr;

   procedure Gen_16 (B : Unsigned_32) is
   begin
      Write_16 (Cur_Sect, Cur_Sect.Pc, B);
      Cur_Sect.Pc := Cur_Sect.Pc + 2;
   end Gen_16;

   procedure Gen_32 (B : Unsigned_32) is
   begin
      Write_32 (Cur_Sect, Cur_Sect.Pc, B);
      Cur_Sect.Pc := Cur_Sect.Pc + 4;
   end Gen_32;

   function Read_32 (Sect : Section_Acc; Pc : Pc_Type) return Unsigned_32
   is
      subtype B4 is Byte_Array_Base (0 .. 3);
      function From_B4 is new Ada.Unchecked_Conversion
        (Source => B4, Target => Unsigned_32);
   begin
      return From_B4 (Sect.Data (Pc + 0 .. Pc + 3));
   end Read_32;

   function Read_Addr (Sect : Section_Acc; Pc : Pc_Type) return Pc_Type
   is
      subtype BPC is Byte_Array_Base (0 .. Pc_Type_Sizeof - 1);
      function From_BPC is new Ada.Unchecked_Conversion
        (Source => BPC, Target => Pc_Type);
   begin
      return From_BPC (Sect.Data (Pc + 0 .. Pc + Pc_Type_Sizeof - 1));
   end Read_Addr;

   procedure Add_32 (Sect : Section_Acc; Pc : Pc_Type; V : Unsigned_32) is
   begin
      Write_32 (Sect, Pc, V + Read_32 (Sect, Pc));
   end Add_32;

   procedure Add_Addr (Sect : Section_Acc; Pc : Pc_Type; V : Pc_Type) is
   begin
      Write_Addr (Sect, Pc, V + Read_Addr (Sect, Pc));
   end Add_Addr;

   procedure Patch_32 (Pc : Pc_Type; V : Unsigned_32) is
   begin
      pragma Assert (Pc + 4 <= Get_Current_Pc);
      Write_32 (Cur_Sect, Pc, V);
   end Patch_32;

   procedure Patch_16 (Pc : Pc_Type; V : Unsigned_32) is
   begin
      pragma Assert (Pc + 2 <= Get_Current_Pc);
      Write_16 (Cur_Sect, Pc, V);
   end Patch_16;

   procedure Patch_8 (Pc : Pc_Type; V : Unsigned_8) is
   begin
      pragma Assert (Pc + 1 <= Get_Current_Pc);
      Write_8 (Cur_Sect, Pc, V);
   end Patch_8;

   procedure Gen_64 (B : Unsigned_64) is
   begin
      Write_64 (Cur_Sect, Cur_Sect.Pc, B);
      Cur_Sect.Pc := Cur_Sect.Pc + 8;
   end Gen_64;

   procedure Gen_Data_8 (B : Unsigned_8) is
   begin
      if Dump_Asm then
         Put_Line (HT & ".byte 0x" & Hex_Image (B));
      end if;
      Gen_8 (Byte (B));
   end Gen_Data_8;

   procedure Gen_Data_16 (B : Unsigned_32) is
   begin
      if Dump_Asm then
         Put_Line (HT & ".half 0x" & Hex_Image (Unsigned_16 (B)));
      end if;
      Gen_16 (B);
   end Gen_Data_16;

   procedure Gen_Data_32 (Sym : Symbol; Offset : Integer_32) is
   begin
      if Dump_Asm then
         if Sym = Null_Symbol then
            Put_Line (HT & ".word 0x" & Hex_Image (Offset));
         else
            if Offset = 0 then
               Put_Line (HT & ".word " & Get_Symbol_Name (Sym));
            else
               Put_Line (HT & ".word " & Get_Symbol_Name (Sym) & " + "
                         & Hex_Image (Offset));
            end if;
         end if;
      end if;
      case Arch is
         when Arch_X86 =>
            Gen_X86_32 (Sym, Offset);
         when Arch_Sparc =>
            Gen_Sparc_32 (Sym, Offset);
         when others =>
            raise Program_Error;
      end case;
   end Gen_Data_32;

   function To_Unsigned_32 (Off : Pc_Type) return Unsigned_32
   is
      Hi : Pc_Type;

      function Shift_Right_Arithmetic (Op : Pc_Type; Amount : Natural)
                                      return Pc_Type;
      pragma Import (Intrinsic, Shift_Right_Arithmetic);
   begin
      --  Check for overflow.
      Hi := Shift_Right_Arithmetic (Off, 31) and 16#ffff_ffff#;
      if Hi /= 0 and Hi /= 16#ffff_ffff# then
         raise Constraint_Error;
      end if;
      return Unsigned_32 (Off and 16#ffff_ffff#);
   end To_Unsigned_32;

   function Create_Symbol (Name : O_Ident; Code : Boolean) return Symbol
   is
   begin
      Symbols.Append (Symbol_Type'(Section => null,
                                   Value => 0,
                                   Scope => Sym_Undef,
                                   Used => False,
                                   Code => Code,
                                   Name => Name,
                                   Relocs => null,
                                   Number => 0));
      return Symbols.Last;
   end Create_Symbol;

   Last_Label : Natural := 1;

   function Create_Local_Symbol return Symbol is
   begin