Add 64 bit integers and doubles
This commit is contained in:
parent
27f06ba208
commit
85a628da2b
@ -6,7 +6,7 @@ ST is a small tracing library written in C99.
|
||||
It is optimized for minimal data usage and aims to be easy to use
|
||||
while also being flexible enough to be integrated in hard real time systems.
|
||||
|
||||
Signal types supported are all integers up to 32 bit as well as their arrays, floats, events and strings.
|
||||
Signal types supported are all integers up to 64 bit, integer arrays up to 32 bit, floats, doubles, events and strings.
|
||||
|
||||

|
||||
|
||||
|
||||
41
st.c
41
st.c
@ -50,11 +50,13 @@ typedef enum
|
||||
st_v1 = 0x21,
|
||||
st_v2 = 0x22,
|
||||
st_v4 = 0x24,
|
||||
st_v8 = 0x28,
|
||||
st_a1 = 0x31,
|
||||
st_a2 = 0x32,
|
||||
st_a4 = 0x34,
|
||||
st_s4 = 0x44,
|
||||
st_f4 = 0x54,
|
||||
st_f8 = 0x58,
|
||||
st_ev = 0x60,
|
||||
} st_type_t;
|
||||
|
||||
@ -72,8 +74,10 @@ typedef struct
|
||||
typedef union
|
||||
{
|
||||
uint32_t u32value;
|
||||
uint64_t u64value;
|
||||
#if (!ST_FLOAT_DISABLE)
|
||||
float f32value;
|
||||
double f64value;
|
||||
#endif
|
||||
} st_convert_t;
|
||||
|
||||
@ -387,6 +391,16 @@ void st_u32trace(const char* const tag, const uint32_t value, const bool skip_ti
|
||||
}
|
||||
}
|
||||
|
||||
void st_u64trace(const char* const tag, const uint64_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
uint32_t ts = skip_time ? 0UL : st_timestamp();
|
||||
tracebuffer_add(ts, st_v8, (uint32_t)(value & 0xFFFFFFFF), 0U, tag);
|
||||
tracebuffer_add(ts, st_v8, (uint32_t)(value >> 32), 1U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void st_s8trace(const char* const tag, const int8_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
@ -403,7 +417,7 @@ void st_s16trace(const char* const tag, const int16_t value, const bool skip_tim
|
||||
}
|
||||
}
|
||||
|
||||
void st_s4trace(const char* const tag, const int32_t value, const bool skip_time)
|
||||
void st_s32trace(const char* const tag, const int32_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
@ -411,6 +425,16 @@ void st_s4trace(const char* const tag, const int32_t value, const bool skip_time
|
||||
}
|
||||
}
|
||||
|
||||
void st_s64trace(const char* const tag, const int64_t value, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
{
|
||||
uint32_t ts = skip_time ? 0UL : st_timestamp();
|
||||
tracebuffer_add(ts, st_v8, (uint32_t)(value & 0xFFFFFFFF), 0U, tag);
|
||||
tracebuffer_add(ts, st_v8, (uint32_t)(value >> 32), 1U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void st_au8trace(const char* const tag, const uint8_t value[const], const uint8_t size, const bool skip_time)
|
||||
{
|
||||
if (s_enabled == true)
|
||||
@ -518,6 +542,17 @@ void st_f32trace(const char* const tag, const float value, const bool skip_time)
|
||||
tracebuffer_add(skip_time ? 0UL : st_timestamp(), st_f4, converter.u32value, 0U, tag);
|
||||
}
|
||||
}
|
||||
|
||||
void st_f64trace(const char* const tag, const double value, const bool skip_time)
|
||||
{
|
||||
st_convert_t converter = { .f64value = value };
|
||||
if (s_enabled == true)
|
||||
{
|
||||
uint32_t ts = skip_time ? 0UL : st_timestamp();
|
||||
tracebuffer_add(ts, st_f8, (uint32_t)(converter.u64value & 0xFFFFFFFF), 0U, tag);
|
||||
tracebuffer_add(ts, st_f8, (uint32_t)(converter.u64value >> 32), 1U, tag);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static size_t frame_preamble(char buffer[], const size_t buffer_size)
|
||||
@ -567,6 +602,8 @@ static size_t pack_frame(char packet_bytes[], const st_trace_t* const p_packet)
|
||||
case st_s4:
|
||||
case st_f4:
|
||||
case st_d4:
|
||||
case st_v8:
|
||||
case st_f8:
|
||||
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 0);
|
||||
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 1);
|
||||
packet_bytes[packet_size++] = ST_BYTE(p_packet->m_value, 2);
|
||||
@ -580,6 +617,8 @@ static size_t pack_frame(char packet_bytes[], const st_trace_t* const p_packet)
|
||||
case st_a2:
|
||||
case st_a4:
|
||||
case st_s4:
|
||||
case st_v8:
|
||||
case st_f8:
|
||||
packet_bytes[packet_size++] = (char)p_packet->m_sub;
|
||||
break;
|
||||
}
|
||||
|
||||
25
st.h
25
st.h
@ -184,6 +184,14 @@ void st_u16trace(const char* const tag, const uint16_t value, const bool skip_ti
|
||||
*/
|
||||
void st_u32trace(const char* const tag, const uint32_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an u64 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] value Value to trace
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void st_u64trace(const char* const tag, const uint64_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an s8 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] value Value to trace
|
||||
@ -208,6 +216,14 @@ void st_s16trace(const char* const tag, const int16_t value, const bool skip_tim
|
||||
*/
|
||||
void st_s32trace(const char* const tag, const int32_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an s64 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] value Value to trace
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void st_s64trace(const char* const tag, const int64_t value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an array of u8 values
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] value Value array to trace
|
||||
@ -272,7 +288,6 @@ void st_as32trace(const char* const tag, const int32_t value[const], const uint8
|
||||
void st_strtrace(const char* const tag, const char* const str, const bool skip_time);
|
||||
|
||||
#if (!ST_FLOAT_DISABLE)
|
||||
|
||||
/** @brief Trace an f32 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] value Value to trace
|
||||
@ -280,6 +295,14 @@ void st_strtrace(const char* const tag, const char* const str, const bool skip_t
|
||||
* @return None
|
||||
*/
|
||||
void st_f32trace(const char* const tag, const float value, const bool skip_time);
|
||||
|
||||
/** @brief Trace an f64 value
|
||||
* @param[in] tag Signal name of the trace
|
||||
* @param[in] value Value to trace
|
||||
* @param[in] skip_time Use last recorded timestamp for this trace
|
||||
* @return None
|
||||
*/
|
||||
void st_f64trace(const char* const tag, const double value, const bool skip_time);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
72
st_record.py
72
st_record.py
@ -170,7 +170,7 @@ def fastlz_decompress_lv1(datain, doutlen):
|
||||
def scan_for_signals(directory, predefined_signals):
|
||||
library_files = ['st.c', 'st.h']
|
||||
rx_events = re.compile(r'st_evtrace\(\"([^\"]+)\"')
|
||||
rx_scalars = re.compile(r'st_([usf])(8|16|32)trace\(\"([^\"]+)\"')
|
||||
rx_scalars = re.compile(r'st_([usf])(8|16|32|64)trace\(\"([^\"]+)\"')
|
||||
rx_arrays = re.compile(r'st_a([us])(8|16|32)trace\(\"([^\"]+)\"\,\s*[^,]+,\s*((?:0x)?[a-zA-Z0-9]+)')
|
||||
rx_strings = re.compile(r'st_strtrace\(\"([^\"]+)\"')
|
||||
signals = {}
|
||||
@ -227,11 +227,13 @@ class Filter:
|
||||
0x21 : "V1",
|
||||
0x22 : "V2",
|
||||
0x24 : "V4",
|
||||
0x28 : "V8",
|
||||
0x31 : "A1",
|
||||
0x32 : "A2",
|
||||
0x34 : "A4",
|
||||
0x44 : "S4",
|
||||
0x54 : "F4",
|
||||
0x58 : "F8",
|
||||
0x60 : "EV"
|
||||
}
|
||||
|
||||
@ -291,7 +293,6 @@ class Filter:
|
||||
return
|
||||
|
||||
tag = self.TAGCODE_LUT[tagcode]
|
||||
|
||||
value = None
|
||||
offset = 1
|
||||
match tag:
|
||||
@ -301,11 +302,11 @@ class Filter:
|
||||
case "D2"|"V2"|"A2":
|
||||
value = decode_binstr(packet[offset:offset+2])
|
||||
offset += 2
|
||||
case "D4"|"V4"|"A4"|"F4"|"S4":
|
||||
case "D4"|"V4"|"V8"|"A4"|"F4"|"F8"|"S4":
|
||||
value = decode_binstr(packet[offset:offset+4])
|
||||
offset += 4
|
||||
sub = None
|
||||
if tag[0] == 'A' or tag[0] == 'S':
|
||||
if tag[0] == 'A' or tag[0] == 'S' or tag == 'V8' or tag == 'F8':
|
||||
sub = decode_binstr(packet[offset:offset+1])
|
||||
offset += 1
|
||||
|
||||
@ -315,7 +316,6 @@ class Filter:
|
||||
except Exception as ex:
|
||||
self.packets_dropped += 1
|
||||
return
|
||||
|
||||
self.process_value(hashtag, value, sub, tag)
|
||||
self.packet_counter += 1
|
||||
|
||||
@ -370,6 +370,7 @@ class VcdSink:
|
||||
def __init__(self, fs, signals, timescale='1 us'):
|
||||
self.writer = VCDWriter(fs, timescale=timescale, date=datetime.datetime.now().isoformat(), version=f"ST v1.0.2")
|
||||
self.skalars = {}
|
||||
self.mw_skalars = {}
|
||||
self.arrays = {}
|
||||
self.strings = {}
|
||||
self.varnames = {}
|
||||
@ -393,6 +394,12 @@ class VcdSink:
|
||||
case 'f32':
|
||||
dtype = 'real'
|
||||
dsize = 32
|
||||
case 'f64':
|
||||
dtype = 'real'
|
||||
dsize = 64
|
||||
case 'u64'|'s64':
|
||||
dtype = 'integer'
|
||||
dsize = 64
|
||||
case 'u32'|'s32':
|
||||
dtype = 'integer'
|
||||
dsize = 32
|
||||
@ -416,6 +423,8 @@ class VcdSink:
|
||||
self.arrays[hvar] = vars
|
||||
elif dtype == 'string':
|
||||
self.strings[hvar] = [self.writer.register_var(hier, name, dtype, size=dsize), ""]
|
||||
elif vtype in ['u64', 's64', 'f64']:
|
||||
self.mw_skalars[hvar] = [self.writer.register_var(hier, name, dtype, size=dsize), 0]
|
||||
else:
|
||||
self.skalars[hvar] = self.writer.register_var(hier, name, dtype, size=dsize)
|
||||
|
||||
@ -472,6 +481,36 @@ class VcdSink:
|
||||
self.packets_dropped += 1
|
||||
self.strings[tag][1] = ""
|
||||
self._emit(timestamp, tag, string, None)
|
||||
elif datatag in ['V8', 'F8']:
|
||||
timestamp = self.timestamp
|
||||
commit = False
|
||||
commit_value = 0
|
||||
if sub == 0:
|
||||
self.mw_skalars[tag][1] = 0
|
||||
self.mw_skalars[tag][1] |= (value << (32 * sub))
|
||||
if sub == 1:
|
||||
commit = True
|
||||
if datatag == 'V8':
|
||||
commit_value = self.mw_skalars[tag][1]
|
||||
elif datatag == 'F8':
|
||||
try:
|
||||
commit_value = struct.unpack("<d", struct.pack("<Q", self.mw_skalars[tag][1]))[0]
|
||||
except Exception as e:
|
||||
print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)
|
||||
if commit:
|
||||
try:
|
||||
self.writer.change(self.mw_skalars[tag][0], timestamp, commit_value)
|
||||
except ValueError:
|
||||
print(f"### {timestamp:012} : {self.varnames[tag]} <= {commit_value} [VAL_ERR] ", flush=True)
|
||||
self.packets_dropped += 1
|
||||
except writer.VCDPhaseError:
|
||||
print(f"### {timestamp:012} : {self.varnames[tag]} <= {commit_value} [PHA_ERR] ", flush=True)
|
||||
self.packets_dropped += 1
|
||||
except:
|
||||
print(f"### {timestamp:012} : {self.varnames[tag]} <= {commit_value} [ERR] ", flush=True)
|
||||
self.packets_dropped += 1
|
||||
|
||||
self._emit(timestamp, tag, commit_value, None)
|
||||
|
||||
# skalar values
|
||||
elif (datatag == 'EV') or (datatag[0] == 'V') or (datatag[0] == 'F'):
|
||||
@ -558,10 +597,7 @@ def main():
|
||||
|
||||
# start recording
|
||||
if enable_tui:
|
||||
if enable_verbose_trace:
|
||||
print("warning: verbose trace is not avaialble in TUI mode")
|
||||
print()
|
||||
tui_record(signals, packet_filter, vcd_sink, timescale)
|
||||
tui_record(signals, packet_filter, vcd_sink, enable_verbose_trace, timescale)
|
||||
else:
|
||||
record(signals, packet_filter, vcd_sink, enable_verbose_trace)
|
||||
|
||||
@ -657,7 +693,7 @@ class SignalTable:
|
||||
not_enough_time_passed = (time - self.lastupdate[signal]) < self.update_interval
|
||||
is_array = signal in self.arraycache
|
||||
is_last_array_index = is_array and (sub == (len(self.arraycache[signal])))
|
||||
if not_enough_time_passed and is_last_array_index:
|
||||
if not_enough_time_passed and not(is_array):
|
||||
return
|
||||
self.lastupdate[signal] = time
|
||||
|
||||
@ -671,7 +707,9 @@ class SignalTable:
|
||||
value_str = f"x{value:04X}"
|
||||
case "u32"|"s32":
|
||||
value_str = f"x{value:08X}"
|
||||
case "f32":
|
||||
case "u64"|"s64":
|
||||
value_str = f"x{value:016X}"
|
||||
case "f32"|"f64":
|
||||
value_str = str(value)
|
||||
case "string":
|
||||
value_str = value.rstrip("\r\n")
|
||||
@ -686,7 +724,7 @@ class SignalTable:
|
||||
|
||||
self.values[signal] = value_str
|
||||
|
||||
def tui_record(signals, packet_filter, vcd_sink, timescale):
|
||||
def tui_record(signals, packet_filter, vcd_sink, enable_verbose_trace, timescale):
|
||||
try:
|
||||
from rich.console import Console
|
||||
from rich.text import Text
|
||||
@ -699,6 +737,12 @@ def tui_record(signals, packet_filter, vcd_sink, timescale):
|
||||
print("error: TUI mode requires the rich package")
|
||||
exit()
|
||||
|
||||
if not(enable_verbose_trace):
|
||||
print("Signals:")
|
||||
for var in signals:
|
||||
print(f" - {var}")
|
||||
print()
|
||||
|
||||
console = Console()
|
||||
noise_buffer = NoiseLineBuffer(lambda text: console.print(f"[blue]{text}"))
|
||||
trace_text = Text("")
|
||||
@ -724,6 +768,7 @@ def tui_record(signals, packet_filter, vcd_sink, timescale):
|
||||
render_time_tm = TotalMaximumProgressUpdater(diag_progress, render_time)
|
||||
comp_time_tm = TotalMaximumProgressUpdater(diag_progress, comp_time)
|
||||
|
||||
if enable_verbose_trace:
|
||||
# set up table layout and signal view
|
||||
# set its update interval to 0.2 seconds in ticks
|
||||
signal_update_interval = int(0.2/timescale)
|
||||
@ -765,7 +810,10 @@ def tui_record(signals, packet_filter, vcd_sink, timescale):
|
||||
for bstr in sys.stdin.buffer:
|
||||
for b in bstr:
|
||||
packet_filter.process(b)
|
||||
if enable_verbose_trace:
|
||||
live_status.update(generate_table(diag_progress, signal_values))
|
||||
else:
|
||||
live_status.update(diag_progress)
|
||||
except KeyboardInterrupt:
|
||||
diag_progress.stop()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user