aboutsummaryrefslogtreecommitdiffstats
path: root/libs/subcircuit/test_large.spl
blob: e33e26985b56d10fe1beb856383661bb51d480dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
225' href='#n225'>225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
--  File operations for interpreter
--  Copyright (C) 2014 Tristan Gingold
--
--  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, see <gnu.org/licenses>.

with Types; use Types;
with Vhdl.Annotations; use Vhdl.Annotations;
with Simul.Execution; use Simul.Execution;
with Simul.Debugger; use Simul.Debugger;
with Simul.Grt_Interface; use Simul.Grt_Interface;
with Grt.Lib;

package body Simul.File_Operation is
   --  Open a file.
   --  See LRM93 3.4.1 for definition of arguments.
   --  IS_TEXT is true if the file format is text.
   --  The purpose of the IS_TEXT is to allow a text implementation of file
   --  type TEXT, defined in std.textio.
   procedure File_Open (Status : out Ghdl_I32;
                        File : Iir_Value_Literal_Acc;
                        External_Name : Iir_Value_Literal_Acc;
                        Mode : Ghdl_I32;
                        Is_Text : Boolean;
                        Return_Status : Boolean)
   is
      Name_Len : constant Ghdl_Index_Type :=
        Ghdl_Index_Type (External_Name.Bounds.D (1).Length);
      Name_Str : aliased Std_String_Uncons (1 .. Name_Len);
      Name_Bnd : aliased Std_String_Bound := Build_Bound (External_Name);
      Name : aliased Std_String := (To_Std_String_Basep (Name_Str'Address),
                                    To_Std_String_Boundp (Name_Bnd'Address));
   begin
      -- Convert the string to an Ada string.
      for I in External_Name.Val_Array.V'Range loop
         Name_Str (Name_Str'First + Ghdl_Index_Type (I - 1)) :=
           Character'Val (External_Name.Val_Array.V (I).E8);
      end loop;

      if Is_Text then
         if Return_Status then
            Status := Ghdl_Text_File_Open_Status
              (File.File, Mode, Name'Unrestricted_Access);
         else
            Ghdl_Text_File_Open (File.File, Mode, Name'Unrestricted_Access);
            Status := Open_Ok;
         end if;
      else
         if Return_Status then
            Status := Ghdl_File_Open_Status
              (File.File, Mode, Name'Unrestricted_Access);
         else
            Ghdl_File_Open (File.File, Mode, Name'Unrestricted_Access);
            Status := Open_Ok;
         end if;
      end if;
   end File_Open;

   --  Open a file.
   procedure File_Open (File : Iir_Value_Literal_Acc;
                        Name : Iir_Value_Literal_Acc;
                        Mode : Iir_Value_Literal_Acc;
                        File_Decl : Iir;
                        Stmt : Iir)
   is
      pragma Unreferenced (Stmt);
      Is_Text : constant Boolean := Get_Text_File_Flag (Get_Type (File_Decl));
      File_Mode : constant Ghdl_I32 := Ghdl_I32 (Mode.E8);
      Status : Ghdl_I32;
   begin
      File_Open (Status, File, Name, File_Mode, Is_Text, False);
      if Status /= Open_Ok then
         raise Program_Error;
      end if;
   end File_Open;

   procedure File_Open_Status (Status : Iir_Value_Literal_Acc;
                               File : Iir_Value_Literal_Acc;
                               Name : Iir_Value_Literal_Acc;
                               Mode : Iir_Value_Literal_Acc;
                               File_Decl : Iir;
                               Stmt : Iir)
   is
      pragma Unreferenced (Stmt);
      Is_Text : constant Boolean := Get_Text_File_Flag (Get_Type (File_Decl));
      File_Mode : constant Ghdl_I32 := Ghdl_I32 (Mode.E8);
      R_Status : Ghdl_I32;
   begin
      File_Open (R_Status, File, Name, File_Mode, Is_Text, True);
      Status.E8 := Ghdl_E8 (R_Status);
   end File_Open_Status;

   function Elaborate_File_Declaration
     (Instance: Block_Instance_Acc; Decl: Iir_File_Declaration)
     return Iir_Value_Literal_Acc
   is
      Def : constant Iir := Get_Type (Decl);
      External_Name : Iir;
      File_Name: Iir_Value_Literal_Acc;
      Is_Text : constant Boolean := Get_Text_File_Flag (Def);
      File_Mode : Ghdl_I32;
      Res : Iir_Value_Literal_Acc;
      Status : Ghdl_I32;
      Mode : Iir_Value_Literal_Acc;
   begin
      if Is_Text then
         Res := Create_File_Value (Ghdl_Text_File_Elaborate);
      else
         declare
            Sig : constant String_Acc := Get_Info (Def).File_Signature;
            Cstr : Ghdl_C_String;
         begin
            if Sig = null then
               Cstr := null;
            else
               Cstr := To_Ghdl_C_String (Sig.all'Address);
            end if;
            Res := Create_File_Value (Ghdl_File_Elaborate (Cstr));
         end;
      end if;

      External_Name := Get_File_Logical_Name (Decl);

      --  LRM93 4.3.1.4
      --  If file open information is not included in a given file declaration,
      --  then the file declared by the declaration is not opened when the file
      --  declaration is elaborated.
      if External_Name = Null_Iir then
         return Res;
      end if;

      File_Name := Execute_Expression (Instance, External_Name);
      if Get_File_Open_Kind (Decl) /= Null_Iir then
         Mode := Execute_Expression (Instance, Get_File_Open_Kind (Decl));
         File_Mode := Ghdl_I32 (Mode.E8);
      else
         case Get_Mode (Decl) is
            when Iir_In_Mode =>
               File_Mode := Read_Mode;
            when Iir_Out_Mode =>
               File_Mode := Write_Mode;
            when others =>
               raise Internal_Error;
         end case;
      end if;
      File_Open (Status, Res, File_Name, File_Mode, Is_Text, False);
      return Res;
   end Elaborate_File_Declaration;

   procedure File_Close_Text (File : Iir_Value_Literal_Acc; Stmt : Iir) is
      pragma Unreferenced (Stmt);
   begin
      Ghdl_Text_File_Close (File.File);
   end File_Close_Text;

   procedure File_Close_Binary (File : Iir_Value_Literal_Acc; Stmt : Iir) is
      pragma Unreferenced (Stmt);
   begin
      Ghdl_File_Close (File.File);
   end File_Close_Binary;

   procedure File_Destroy_Text (File : Iir_Value_Literal_Acc) is
   begin
      Ghdl_Text_File_Finalize (File.File);
   end File_Destroy_Text;

   procedure File_Destroy_Binary (File : Iir_Value_Literal_Acc) is
   begin
      Ghdl_File_Finalize (File.File);
   end File_Destroy_Binary;


   procedure Write_Binary (File: Iir_Value_Literal_Acc;
                           Value: Iir_Value_Literal_Acc) is
   begin
      case Value.Kind is
         when Iir_Value_B1 =>
            Ghdl_Write_Scalar (File.File, Ghdl_Ptr (Value.B1'Address), 1);
         when Iir_Value_I64 =>
            Ghdl_Write_Scalar (File.File, Ghdl_Ptr (Value.I64'Address), 8);
         when Iir_Value_E8 =>
            Ghdl_Write_Scalar (File.File, Ghdl_Ptr (Value.E8'Address), 1);
         when Iir_Value_E32 =>
            Ghdl_Write_Scalar (File.File, Ghdl_Ptr (Value.E32'Address), 4);
         when Iir_Value_F64 =>
            Ghdl_Write_Scalar (File.File, Ghdl_Ptr (Value.F64'Address), 8);
         when Iir_Value_Array =>
            for I in Value.Bounds.D'Range loop
               Ghdl_Write_Scalar
                 (File.File, Ghdl_Ptr (Value.Bounds.D (I).Length'Address), 4);
            end loop;
            for I in Value.Val_Array.V'Range loop
               Write_Binary (File, Value.Val_Array.V (I));
            end loop;
         when Iir_Value_Record =>
            for I in Value.Val_Record.V'Range loop
               Write_Binary (File, Value.Val_Record.V (I));
            end loop;
         when others =>
            raise Internal_Error;
      end case;
   end Write_Binary;

   procedure Write_Text (File: Iir_Value_Literal_Acc;
                         Value: Iir_Value_Literal_Acc)
   is
      Val_Len : constant Ghdl_Index_Type :=
        Ghdl_Index_Type (Value.Bounds.D (1).Length);
      Val_Str : aliased Std_String_Uncons (1 .. Val_Len);
      Val_Bnd : aliased Std_String_Bound := Build_Bound (Value);
      Val : aliased Std_String := (To_Std_String_Basep (Val_Str'Address),
                                    To_Std_String_Boundp (Val_Bnd'Address));
   begin
      -- Convert the string to an Ada string.
      for I in Value.Val_Array.V'Range loop
         Val_Str (Val_Str'First + Ghdl_Index_Type (I - 1)) :=
           Character'Val (Value.Val_Array.V (I).E8);
      end loop;

      Ghdl_Text_Write (File.File, Val'Unrestricted_Access);
   end Write_Text;

   function Endfile (File : Iir_Value_Literal_Acc; Stmt : Iir)
                    return Boolean
   is
      pragma Unreferenced (Stmt);
   begin
      return Grt.Files.Ghdl_File_Endfile (File.File);
   end Endfile;

   procedure Read_Length_Text (File : Iir_Value_Literal_Acc;
                               Value : Iir_Value_Literal_Acc;
                               Length : Iir_Value_Literal_Acc)
   is
      Val_Len : constant Ghdl_Index_Type :=
        Ghdl_Index_Type (Value.Bounds.D (1).Length);
      Val_Str : aliased Std_String_Uncons (1 .. Val_Len);
      Val_Bnd : aliased Std_String_Bound := Build_Bound (Value);
      Val : aliased Std_String := (To_Std_String_Basep (Val_Str'Address),
                                   To_Std_String_Boundp (Val_Bnd'Address));
      Len : Std_Integer;
   begin
      Len := Ghdl_Text_Read_Length (File.File, Val'Unrestricted_Access);
      for I in 1 .. Len loop
         Value.Val_Array.V (Iir_Index32 (I)).E8 :=
           Character'Pos (Val_Str (Ghdl_Index_Type (I)));
      end loop;
      Length.I64 := Ghdl_I64 (Len);
   end Read_Length_Text;

   procedure Untruncated_Text_Read (File : Iir_Value_Literal_Acc;
                                    Str : Iir_Value_Literal_Acc;
                                    Length : Iir_Value_Literal_Acc)
   is
      Len : Std_Integer;
      Val_Len : constant Ghdl_Index_Type :=
        Ghdl_Index_Type (Str.Bounds.D (1).Length);
      Val_Str : aliased Std_String_Uncons (1 .. Val_Len);
      Val_Bnd : aliased Std_String_Bound := Build_Bound (Str);
      Val : aliased Std_String := (To_Std_String_Basep (Val_Str'Address),
                                   To_Std_String_Boundp (Val_Bnd'Address));
   begin
      Ghdl_Untruncated_Text_Read
        (File.File, Val'Unrestricted_Access, Len'Unrestricted_Access);
      for I in 1 .. Len loop
         Str.Val_Array.V (Iir_Index32 (I)).E8 :=
           Character'Pos (Val_Str (Ghdl_Index_Type (I)));
      end loop;
      Length.I64 := Ghdl_I64 (Len);
   end Untruncated_Text_Read;

   procedure Read_Binary (File: Iir_Value_Literal_Acc;
                          Value: Iir_Value_Literal_Acc)
   is
   begin
      case Value.Kind is
         when Iir_Value_B1 =>
            Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Value.B1'Address), 1);
         when Iir_Value_I64 =>
            Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Value.I64'Address), 8);
         when Iir_Value_E8 =>
            Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Value.E8'Address), 1);
         when Iir_Value_E32 =>
            Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Value.E32'Address), 4);
         when Iir_Value_F64 =>
            Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Value.F64'Address), 8);
         when Iir_Value_Array =>
            for I in Value.Bounds.D'Range loop
               declare
                  Len : Iir_Index32;
               begin
                  Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Len'Address), 4);
                  if Len /= Value.Bounds.D (I).Length then
                     Error_Msg_Constraint (Null_Iir); --  FIXME: loc
                  end if;
               end;
            end loop;
            for I in Value.Val_Array.V'Range loop
               Read_Binary (File, Value.Val_Array.V (I));
            end loop;
         when Iir_Value_Record =>
            for I in Value.Val_Record.V'Range loop
               Read_Binary (File, Value.Val_Record.V (I));
            end loop;
         when others =>
            raise Internal_Error;
      end case;
   end Read_Binary;

   procedure Read_Length_Binary (File : Iir_Value_Literal_Acc;
                                 Value : Iir_Value_Literal_Acc;
                                 Length : Iir_Value_Literal_Acc)
   is
      Len : Iir_Index32;
   begin
      Ghdl_Read_Scalar (File.File, Ghdl_Ptr (Len'Address), 4);
      for I in 1 .. Len loop
         if I <= Value.Bounds.D (1).Length then
            Read_Binary (File, Value.Val_Array.V (I));
         else
            --  FIXME: for empty arrays ??
            --  Lose_Binary (File, Value.Val_Array (0));
            raise Internal_Error;
         end if;
      end loop;
      Length.I64 := Ghdl_I64 (Len);
   end Read_Length_Binary;

   procedure Flush (File : Iir_Value_Literal_Acc) is
   begin
      Ghdl_File_Flush (File.File);
   end Flush;

   procedure Textio_Write_Real (Str : Iir_Value_Literal_Acc;
                                Len : Iir_Value_Literal_Acc;
                                Val : Ghdl_F64;
                                Ndigits : Std_Integer)
   is
      Len_Arg : aliased Std_Integer;
      Str_Len : constant Ghdl_Index_Type :=
        Ghdl_Index_Type (Str.Bounds.D (1).Length);
      Str_Str : aliased Std_String_Uncons (1 .. Str_Len);
      Str_Bnd : aliased Std_String_Bound := Build_Bound (Str);
      Str_Arg : aliased Std_String := (To_Std_String_Basep (Str_Str'Address),
                                       To_Std_String_Boundp (Str_Bnd'Address));
   begin
      Grt.Lib.Textio_Write_Real
        (Str_Arg'Unrestricted_Access, Len_Arg'Unrestricted_Access,
         Val, Ndigits);
      for I in 1 .. Len_Arg loop
         Str.Val_Array.V (Iir_Index32 (I)).E8 :=
           Character'Pos (Str_Str (Ghdl_Index_Type (I)));
      end loop;
      Len.I64 := Ghdl_I64 (Len_Arg);
   end Textio_Write_Real;

   function Textio_Read_Real (Str : Iir_Value_Literal_Acc) return Ghdl_F64
   is
      Str_Len : constant Ghdl_Index_Type :=
        Ghdl_Index_Type (Str.Bounds.D (1).Length);
      Str_Str : aliased Std_String_Uncons (1 .. Str_Len);
      Str_Bnd : aliased Std_String_Bound := Build_Bound (Str);
      Str_Arg : aliased Std_String := (To_Std_String_Basep (Str_Str'Address),
                                       To_Std_String_Boundp (Str_Bnd'Address));
   begin
      for I in Str.Val_Array.V'Range loop
         Str_Str (Ghdl_Index_Type (I)) :=
           Character'Val (Str.Val_Array.V (I).E8);
      end loop;
      return Grt.Lib.Textio_Read_Real (Str_Arg'Unrestricted_Access);
   end Textio_Read_Real;
end Simul.File_Operation;