blob: 487397985431349094a3baf1ea330922459b05dc [file] [log] [blame]
Nico Huber5e9b1b52016-10-08 22:09:33 +02001--
2-- Copyright (C) 2015 secunet Security Networks AG
3--
4-- This program is free software; you can redistribute it and/or modify
5-- it under the terms of the GNU General Public License as published by
Nico Huberaab715f2016-10-18 00:22:25 +02006-- the Free Software Foundation; either version 2 of the License, or
7-- (at your option) any later version.
Nico Huber5e9b1b52016-10-08 22:09:33 +02008--
9-- This program is distributed in the hope that it will be useful,
10-- but WITHOUT ANY WARRANTY; without even the implied warranty of
11-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-- GNU General Public License for more details.
13--
14
Nico Huber5e9b1b52016-10-08 22:09:33 +020015with HW.Time;
16with HW.Debug_Sink;
17
18use type HW.Word64;
19use type HW.Int64;
20
21package body HW.Debug
22with
23 SPARK_Mode => Off
24is
Jeremy Compostella95ad8c52022-11-21 18:07:06 -070025 -- Placing the two variables below in the .bss section set them to
26 -- their desired default value which is respectively False and
27 -- 0. It helps to integrate the libhwbase library debug package in
28 -- environments where global initialized variables are not
29 -- supported such as coreboot romstage.
30 Middle_Of_Line : Boolean;
31 pragma Linker_Section (Middle_Of_Line, ".bss");
32 Register_Write_Delay_Nanoseconds : Word64;
33 pragma Linker_Section (Register_Write_Delay_Nanoseconds, ".bss");
Nico Huber5e9b1b52016-10-08 22:09:33 +020034
35 type Base_Range is new Positive range 2 .. 16;
36 type Width_Range is new Natural range 0 .. 64;
37
38 procedure Put_By_Base
39 (Item : Word64;
40 Min_Width : Width_Range;
41 Base : Base_Range);
42
43 procedure Do_Put_Int64
44 (Item : Int64);
45
46 ----------------------------------------------------------------------------
47
48 procedure Put_Time
49 is
50 Now_US : Int64;
51 begin
Jeremy Compostella95ad8c52022-11-21 18:07:06 -070052 if not Middle_Of_Line then
53 Middle_Of_Line := True;
Nico Huber5e9b1b52016-10-08 22:09:33 +020054 Now_US := Time.Now_US;
55 Debug_Sink.Put_Char ('[');
56 Do_Put_Int64 ((Now_US / 1_000_000) mod 1_000_000);
57 Debug_Sink.Put_Char ('.');
58 Put_By_Base (Word64 (Now_US mod 1_000_000), 6, 10);
59 Debug_Sink.Put ("] ");
60 end if;
61 end Put_Time;
62
63 ----------------------------------------------------------------------------
64
65 procedure Put (Item : String) is
66 begin
67 Put_Time;
68 HW.Debug_Sink.Put (Item);
69 end Put;
70
71 procedure Put_Line (Item : String) is
72 begin
73 Put (Item);
74 New_Line;
75 end Put_Line;
76
77 procedure New_Line is
78 begin
79 HW.Debug_Sink.New_Line;
Jeremy Compostella95ad8c52022-11-21 18:07:06 -070080 Middle_Of_Line := False;
Nico Huber5e9b1b52016-10-08 22:09:33 +020081 end New_Line;
82
83 ----------------------------------------------------------------------------
84
85 procedure Put_By_Base
86 (Item : Word64;
87 Min_Width : Width_Range;
88 Base : Base_Range)
89 is
90 Temp : Word64 := Item;
91
92 subtype Chars_Range is Width_Range range 0 .. 63;
93 Index : Width_Range := 0;
94
95 type Chars_Array is array (Chars_Range) of Character;
96 Chars : Chars_Array := (others => '0');
97
98 Digit : Natural;
99 begin
100 while Temp > 0 loop
101 Digit := Natural (Temp rem Word64 (Base));
102 if Digit < 10 then
103 Chars (Index) := Character'Val (Character'Pos ('0') + Digit);
104 else
105 Chars (Index) := Character'Val (Character'Pos ('a') + Digit - 10);
106 end if;
107 Temp := Temp / Word64 (Base);
108 Index := Index + 1;
109 end loop;
110 if Index < Min_Width then
111 Index := Min_Width;
112 end if;
113 for I in reverse Width_Range range 0 .. Index - 1 loop
114 HW.Debug_Sink.Put_Char (Chars (I));
115 end loop;
116 end Put_By_Base;
117
118 ----------------------------------------------------------------------------
119
120 procedure Put_Word
121 (Item : Word64;
122 Min_Width : Width_Range;
123 Print_Ox : Boolean := True) is
124 begin
125 Put_Time;
126 if Print_Ox then
127 Put ("0x");
128 end if;
129 Put_By_Base (Item, Min_Width, 16);
130 end Put_Word;
131
132 procedure Put_Word8 (Item : Word8) is
133 begin
134 Put_Word (Word64 (Item), 2);
135 end Put_Word8;
136
137 procedure Put_Word16 (Item : Word16) is
138 begin
139 Put_Word (Word64 (Item), 4);
140 end Put_Word16;
141
142 procedure Put_Word32 (Item : Word32) is
143 begin
144 Put_Word (Word64 (Item), 8);
145 end Put_Word32;
146
147 procedure Put_Word64 (Item : Word64) is
148 begin
149 Put_Word (Item, 16);
150 end Put_Word64;
151
152 ----------------------------------------------------------------------------
153
154 procedure Do_Put_Int64 (Item : Int64)
155 is
156 Temp : Word64;
157 begin
158 if Item < 0 then
159 Debug_Sink.Put_Char ('-');
160 Temp := Word64 (-Item);
161 else
162 Temp := Word64 (Item);
163 end if;
164 Put_By_Base (Temp, 1, 10);
165 end Do_Put_Int64;
166
167 procedure Put_Int64 (Item : Int64)
168 is
169 begin
170 Put_Time;
171 Do_Put_Int64 (Item);
172 end Put_Int64;
173
174 procedure Put_Int8 (Item : Int8) is
175 begin
176 Put_Int64 (Int64 (Item));
177 end Put_Int8;
178
179 procedure Put_Int16 (Item : Int16) is
180 begin
181 Put_Int64 (Int64 (Item));
182 end Put_Int16;
183
184 procedure Put_Int32 (Item : Int32) is
185 begin
186 Put_Int64 (Int64 (Item));
187 end Put_Int32;
188
189 ----------------------------------------------------------------------------
190
191 procedure Put_Reg8 (Name : String; Item : Word8) is
192 begin
193 Put (Name);
194 Put (": ");
195 Put_Word8 (Item);
196 New_Line;
197 end Put_Reg8;
198
199 procedure Put_Reg16 (Name : String; Item : Word16)
200 is
201 begin
202 Put (Name);
203 Put (": ");
204 Put_Word16 (Item);
205 New_Line;
206 end Put_Reg16;
207
208 procedure Put_Reg32 (Name : String; Item : Word32)
209 is
210 begin
211 Put (Name);
212 Put (": ");
213 Put_Word32 (Item);
214 New_Line;
215 end Put_Reg32;
216
217 procedure Put_Reg64 (Name : String; Item : Word64)
218 is
219 begin
220 Put (Name);
221 Put (": ");
222 Put_Word64 (Item);
223 New_Line;
224 end Put_Reg64;
225
226 ----------------------------------------------------------------------------
227
228 procedure Put_Buffer
229 (Name : String;
230 Buf : Buffer;
231 Len : Buffer_Range)
232 is
233 Line_Start, Left : Natural;
234 begin
235 if Len = 0 then
236 if Name'Length > 0 then
237 Put (Name);
238 Put_Line ("+0x00:");
239 end if;
240 else
241 Line_Start := 0;
242 Left := Len - 1;
243 for I in Natural range 1 .. ((Len + 15) / 16) loop
244 if Name'Length > 0 then
245 Put (Name);
246 Debug_Sink.Put_Char ('+');
247 Put_Word16 (Word16 (Line_Start));
248 Put (": ");
249 end if;
250 for J in Natural range 0 .. Natural'Min (7, Left)
251 loop
252 Put_Word (Word64 (Buf (Line_Start + J)), 2, False);
253 Debug_Sink.Put_Char (' ');
254 end loop;
255
256 Debug_Sink.Put_Char (' ');
257 for J in Natural range 8 .. Natural'Min (15, Left)
258 loop
Nico Huber455ed642018-05-18 15:21:23 +0200259 Put_Word (Word64 (Buf (Line_Start + J)), 2, False);
Nico Huber5e9b1b52016-10-08 22:09:33 +0200260 Debug_Sink.Put_Char (' ');
261 end loop;
262 New_Line;
263
264 Line_Start := Line_Start + 16;
265 Left := Left - Natural'Min (Left, 16);
266 end loop;
267 end if;
268 end Put_Buffer;
269
270 ----------------------------------------------------------------------------
271
272 procedure Set_Register_Write_Delay (Value : Word64)
273 is
274 begin
275 Register_Write_Delay_Nanoseconds := Value;
276 end Set_Register_Write_Delay;
277
278 ----------------------------------------------------------------------------
279
Nico Huber455ed642018-05-18 15:21:23 +0200280 procedure Register_Write_Wait
Nico Huber5e9b1b52016-10-08 22:09:33 +0200281 is
282 begin
283 if Register_Write_Delay_Nanoseconds > 0 then
284 Time.U_Delay (Natural ((Register_Write_Delay_Nanoseconds + 999) / 1000));
285 end if;
286 end Register_Write_Wait;
287
288end HW.Debug;
289
290-- vim: set ts=8 sts=3 sw=3 et: