blob: b9f9f896b1ad9c86d16f640cee459d9502b68259 [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;
Nico Huber5e9b1b52016-10-08 22:09:33 +020019
20package body HW.Debug
21with
22 SPARK_Mode => Off
23is
Jeremy Compostella95ad8c52022-11-21 18:07:06 -070024 -- Placing the two variables below in the .bss section set them to
25 -- their desired default value which is respectively False and
26 -- 0. It helps to integrate the libhwbase library debug package in
27 -- environments where global initialized variables are not
28 -- supported such as coreboot romstage.
29 Middle_Of_Line : Boolean;
30 pragma Linker_Section (Middle_Of_Line, ".bss");
31 Register_Write_Delay_Nanoseconds : Word64;
32 pragma Linker_Section (Register_Write_Delay_Nanoseconds, ".bss");
Nico Huber5e9b1b52016-10-08 22:09:33 +020033
34 type Base_Range is new Positive range 2 .. 16;
35 type Width_Range is new Natural range 0 .. 64;
36
37 procedure Put_By_Base
38 (Item : Word64;
39 Min_Width : Width_Range;
40 Base : Base_Range);
41
42 procedure Do_Put_Int64
43 (Item : Int64);
44
45 ----------------------------------------------------------------------------
46
47 procedure Put_Time
48 is
49 Now_US : Int64;
50 begin
Jeremy Compostella95ad8c52022-11-21 18:07:06 -070051 if not Middle_Of_Line then
52 Middle_Of_Line := True;
Nico Huber5e9b1b52016-10-08 22:09:33 +020053 Now_US := Time.Now_US;
54 Debug_Sink.Put_Char ('[');
55 Do_Put_Int64 ((Now_US / 1_000_000) mod 1_000_000);
56 Debug_Sink.Put_Char ('.');
57 Put_By_Base (Word64 (Now_US mod 1_000_000), 6, 10);
58 Debug_Sink.Put ("] ");
59 end if;
60 end Put_Time;
61
62 ----------------------------------------------------------------------------
63
64 procedure Put (Item : String) is
65 begin
66 Put_Time;
67 HW.Debug_Sink.Put (Item);
68 end Put;
69
70 procedure Put_Line (Item : String) is
71 begin
72 Put (Item);
73 New_Line;
74 end Put_Line;
75
76 procedure New_Line is
77 begin
78 HW.Debug_Sink.New_Line;
Jeremy Compostella95ad8c52022-11-21 18:07:06 -070079 Middle_Of_Line := False;
Nico Huber5e9b1b52016-10-08 22:09:33 +020080 end New_Line;
81
82 ----------------------------------------------------------------------------
83
84 procedure Put_By_Base
85 (Item : Word64;
86 Min_Width : Width_Range;
87 Base : Base_Range)
88 is
89 Temp : Word64 := Item;
90
91 subtype Chars_Range is Width_Range range 0 .. 63;
92 Index : Width_Range := 0;
93
94 type Chars_Array is array (Chars_Range) of Character;
95 Chars : Chars_Array := (others => '0');
96
97 Digit : Natural;
98 begin
99 while Temp > 0 loop
100 Digit := Natural (Temp rem Word64 (Base));
101 if Digit < 10 then
102 Chars (Index) := Character'Val (Character'Pos ('0') + Digit);
103 else
104 Chars (Index) := Character'Val (Character'Pos ('a') + Digit - 10);
105 end if;
106 Temp := Temp / Word64 (Base);
107 Index := Index + 1;
108 end loop;
109 if Index < Min_Width then
110 Index := Min_Width;
111 end if;
112 for I in reverse Width_Range range 0 .. Index - 1 loop
113 HW.Debug_Sink.Put_Char (Chars (I));
114 end loop;
115 end Put_By_Base;
116
117 ----------------------------------------------------------------------------
118
119 procedure Put_Word
120 (Item : Word64;
121 Min_Width : Width_Range;
122 Print_Ox : Boolean := True) is
123 begin
124 Put_Time;
125 if Print_Ox then
126 Put ("0x");
127 end if;
128 Put_By_Base (Item, Min_Width, 16);
129 end Put_Word;
130
131 procedure Put_Word8 (Item : Word8) is
132 begin
133 Put_Word (Word64 (Item), 2);
134 end Put_Word8;
135
136 procedure Put_Word16 (Item : Word16) is
137 begin
138 Put_Word (Word64 (Item), 4);
139 end Put_Word16;
140
141 procedure Put_Word32 (Item : Word32) is
142 begin
143 Put_Word (Word64 (Item), 8);
144 end Put_Word32;
145
146 procedure Put_Word64 (Item : Word64) is
147 begin
148 Put_Word (Item, 16);
149 end Put_Word64;
150
151 ----------------------------------------------------------------------------
152
153 procedure Do_Put_Int64 (Item : Int64)
154 is
155 Temp : Word64;
156 begin
157 if Item < 0 then
158 Debug_Sink.Put_Char ('-');
159 Temp := Word64 (-Item);
160 else
161 Temp := Word64 (Item);
162 end if;
163 Put_By_Base (Temp, 1, 10);
164 end Do_Put_Int64;
165
166 procedure Put_Int64 (Item : Int64)
167 is
168 begin
169 Put_Time;
170 Do_Put_Int64 (Item);
171 end Put_Int64;
172
173 procedure Put_Int8 (Item : Int8) is
174 begin
175 Put_Int64 (Int64 (Item));
176 end Put_Int8;
177
178 procedure Put_Int16 (Item : Int16) is
179 begin
180 Put_Int64 (Int64 (Item));
181 end Put_Int16;
182
183 procedure Put_Int32 (Item : Int32) is
184 begin
185 Put_Int64 (Int64 (Item));
186 end Put_Int32;
187
188 ----------------------------------------------------------------------------
189
190 procedure Put_Reg8 (Name : String; Item : Word8) is
191 begin
192 Put (Name);
193 Put (": ");
194 Put_Word8 (Item);
195 New_Line;
196 end Put_Reg8;
197
198 procedure Put_Reg16 (Name : String; Item : Word16)
199 is
200 begin
201 Put (Name);
202 Put (": ");
203 Put_Word16 (Item);
204 New_Line;
205 end Put_Reg16;
206
207 procedure Put_Reg32 (Name : String; Item : Word32)
208 is
209 begin
210 Put (Name);
211 Put (": ");
212 Put_Word32 (Item);
213 New_Line;
214 end Put_Reg32;
215
216 procedure Put_Reg64 (Name : String; Item : Word64)
217 is
218 begin
219 Put (Name);
220 Put (": ");
221 Put_Word64 (Item);
222 New_Line;
223 end Put_Reg64;
224
225 ----------------------------------------------------------------------------
226
227 procedure Put_Buffer
228 (Name : String;
229 Buf : Buffer;
230 Len : Buffer_Range)
231 is
232 Line_Start, Left : Natural;
233 begin
234 if Len = 0 then
235 if Name'Length > 0 then
236 Put (Name);
237 Put_Line ("+0x00:");
238 end if;
239 else
240 Line_Start := 0;
241 Left := Len - 1;
242 for I in Natural range 1 .. ((Len + 15) / 16) loop
243 if Name'Length > 0 then
244 Put (Name);
245 Debug_Sink.Put_Char ('+');
246 Put_Word16 (Word16 (Line_Start));
247 Put (": ");
248 end if;
249 for J in Natural range 0 .. Natural'Min (7, Left)
250 loop
251 Put_Word (Word64 (Buf (Line_Start + J)), 2, False);
252 Debug_Sink.Put_Char (' ');
253 end loop;
254
255 Debug_Sink.Put_Char (' ');
256 for J in Natural range 8 .. Natural'Min (15, Left)
257 loop
Nico Huber455ed642018-05-18 15:21:23 +0200258 Put_Word (Word64 (Buf (Line_Start + J)), 2, False);
Nico Huber5e9b1b52016-10-08 22:09:33 +0200259 Debug_Sink.Put_Char (' ');
260 end loop;
261 New_Line;
262
263 Line_Start := Line_Start + 16;
264 Left := Left - Natural'Min (Left, 16);
265 end loop;
266 end if;
267 end Put_Buffer;
268
269 ----------------------------------------------------------------------------
270
271 procedure Set_Register_Write_Delay (Value : Word64)
272 is
273 begin
274 Register_Write_Delay_Nanoseconds := Value;
275 end Set_Register_Write_Delay;
276
277 ----------------------------------------------------------------------------
278
Nico Huber455ed642018-05-18 15:21:23 +0200279 procedure Register_Write_Wait
Nico Huber5e9b1b52016-10-08 22:09:33 +0200280 is
281 begin
282 if Register_Write_Delay_Nanoseconds > 0 then
283 Time.U_Delay (Natural ((Register_Write_Delay_Nanoseconds + 999) / 1000));
284 end if;
285 end Register_Write_Wait;
286
287end HW.Debug;
288
289-- vim: set ts=8 sts=3 sw=3 et: