new(slavelog parser): parser for asdtp section

- a lot of boilerplates...
- there should be smarter way
This commit is contained in:
Wataru Otsubo 2024-10-25 22:50:48 +09:00
parent 9a4a4e8952
commit 3b490cd28c
8 changed files with 8938 additions and 0 deletions

View file

@ -9,6 +9,7 @@ using Dates
include("parse_qaqc_master_log.jl")
include("parse_clock.jl")
include("SlaveLogParser.jl")
include("create_table.jl")
include("download_csv.jl")

361
src/SlaveLogParser.jl Normal file
View file

@ -0,0 +1,361 @@
module SlaveLogParser
using StaticArrays
using AutoHashEquals
const HEADER_QSPIP_START = "=============== Test QAPIp Start ==============="
const HEADER_POWER_START = "=============== Test Power Start ==============="
const HEADER_ASDTP_START = "=============== Test ASDTP Start ==============="
const HEADER_RECOV_START = "=============== Test Recov Start ==============="
HEADER_STARTS =
[HEADER_QSPIP_START, HEADER_POWER_START, HEADER_ASDTP_START, HEADER_RECOV_START]
"""
Indicate parser state.
Default is `MODE_NONE`.
In `MODE_NONE`, each line is feeded into parser to detect the start of each section.
"""
@enum SlaveLogSection begin
MODE_NONE
MODE_QSPIP
MODE_POWER
MODE_ASDTP
MODE_RECOV
end
struct PowerResult
result_3v3d::Float64
result_3v3a::Float64
result_n3va::Float64
fpga_temp::Float64
result::Bool
end
struct SlaveLogResult end
"""
get_psbid_runid_from_filename(filename::AbstractString)::Tuple{Int64,Int64,Bool}
Extract info from slave log filename.
"""
function get_psbid_runid_from_filename(filename::AbstractString)::Tuple{Int64, Int64, Bool}
main, _ext = splitext(filename)
parts = split(main, '_')
psbid = parse(Int64, parts[1])
runid = parse(Int64, parts[2])
islongrun = if length(parts) == 3
true
else
false
end
(psbid, runid, islongrun)
end
function is_valid_slavelog(filename::AbstractString)::Bool
error("not yet implemented")
end
"""
detect_mode_start(line::AbstractString)
Detect [`SlaveLogSection`](@ref) from section starting header line.
If the line doesn't match any section, returns `nothing`.
"""
function detect_mode_start(line::AbstractString)
if line == HEADER_QSPIP_START
MODE_QSPIP
elseif line == HEADER_POWER_START
MODE_POWER
elseif line == HEADER_ASDTP_START
MODE_ASDTP
elseif line == HEADER_RECOV_START
MODE_RECOV
else
nothing
end
end
"""
detect_mode_start!(mode::SlaveLogSection, line::AbstractString)
Detect mode from the `line` and update `mode`.
"""
function detect_mode_start(mode::SlaveLogSection, line::AbstractString)
newmode = detect_mode_start(line)
if !isnothing(newmode)
mode = newmode
end
mode
end
"""
parse_qspip_section(lines::Base.Iterators.Stateful)
Parse QSPIp section of given stateful iterator of log.
# Args
- `lines`: Stateful iterator of slave log file lines
"""
function parse_qspip_section!(lines::Base.Iterators.Stateful)
# TODO
nothing
end
"""
parse_power_section(lines::Base.Iterators.Stateful)
Parse Power section of given stateful iterator of log.
# Args
- `lines`: Stateful iterator of slave log file lines
"""
function parse_power_section!(lines::Base.Iterators.Stateful)
# TODO
nothing
end
"""
Measurement result for asic in asdtp test.
"""
@auto_hash_equals struct AsdtpMeasurement
before::Float64
current::Float64
next::Float64
end
AsdtpMeasurement(x::NTuple{3, <:Real}) = AsdtpMeasurement(x...)
function Base.parse(::Type{AsdtpMeasurement}, s::AbstractString)
v = split(s, ':')
@assert length(v) == 3
AsdtpMeasurement(parse(Float64, v[1]), parse(Float64, v[2]), parse(Float64, v[3]))
end
@auto_hash_equals struct AsdtpResult
reconfig_done::Int64
always_hit_flag::Int64
autoreconfig::Union{Bool, Missing}
asdtp_main::Union{Vector{Vector{AsdtpMeasurement}}, Missing}
asdtp_reset::Int64
asdtp_total::Int64
reconfig_done_2::Int64
always_hit_flag_2::Int64
si_done::UInt64
lolb_in::UInt64
ppconfig_done::UInt64
ppconfig_error::UInt64
pllld_fail_counter::UInt64
ppconfig_fail_counter::UInt64
pp_pllds::MVector{8, UInt32}
end
"""
parse_asdtp_section(lines::Base.Iterators.Stateful)
Parse ASDTP section of given stateful iterator of log.
# Args
- `lines`: Stateful iterator of slave log file lines
"""
function parse_asdtp_section!(lines::Base.Iterators.Stateful)
line = popfirst!(lines)
result_reconfig_done = let
m = match(r"^reconfig_done = (\d+)$", line)
parse(Int64, m[1])
end
line = popfirst!(lines)
result_always_hit_flag = let
m = match(r"^always_hit_flag = (\d+)$", line)
parse(Int64, m[1])
end
line = popfirst!(lines)
result_autoreconfig = if line == "Autoreconfig done"
true
elseif line == "Autoreconfig fail"
false
else
missing
end
result_asdtp_main = if !ismissing(result_autoreconfig) && result_autoreconfig
line_count = 0
line_count += 1
results = map(_ -> AsdtpMeasurement[], 1:8)
for asic_id in 1:8
header_line = "----PP$(asic_id)----"
while line != header_line
line = popfirst!(lines)
line_count += 1
end
for _ in 1:32
line = popfirst!(lines)
line_count += 1
mes = parse(AsdtpMeasurement, line)
push!(results[asic_id], mes)
end
end
@assert length(results[1]) == 32 "unexpected length: $(length(results[1]))"
line = popfirst!(lines)
@assert line == "100"
results
else
missing
end
line = popfirst!(lines)
result_asdtp_reset, result_asdtp_total = let
m = match(r"^ASDTP : (\d+) times reset : result = (\d+)$", line)
parse(Int64, m[1]), parse(Int64, m[2])
end
line = popfirst!(lines)
result_reconfig_done_2 = let
m = match(r"^reconfig_done = (\d+)$", line)
parse(Int64, m[1])
end
line = popfirst!(lines)
result_always_hit_flag_2 = let
m = match(r"^always_hit_flag = (\d+)$", line)
parse(Int64, m[1])
end
line = popfirst!(lines)
@assert line == ""
line = popfirst!(lines)
@assert line == "------- Done check -------" "actual line: $line"
line = popfirst!(lines)
result_si_done = let
m = match(r"^Si_done = (0x[[:xdigit:]]+)$", line)
parse(UInt64, m[1])
end
line = popfirst!(lines)
result_lolb_in = let
m = match(r"^LOLB_in = (0x[[:xdigit:]]+)$", line)
parse(UInt64, m[1])
end
line = popfirst!(lines)
result_ppconfig_done = let
m = match(r"^PPconfig_done = (0x[[:xdigit:]]+)$", line)
parse(UInt64, m[1])
end
line = popfirst!(lines)
result_ppconfig_error = let
m = match(r"^PPconfig_error = (0x[[:xdigit:]]+)$", line)
parse(UInt64, m[1])
end
line = popfirst!(lines)
result_pllld_fail_counter = let
m = match(r"^PLLLD_fail_counter = (0x[[:xdigit:]]+)$", line)
parse(UInt64, m[1])
end
line = popfirst!(lines)
result_ppconfig_fail_counter = let
m = match(r"^PPconfig_fail_counter = (0x[[:xdigit:]]+)$", line)
parse(UInt64, m[1])
end
result_pp_pllds = MVector{8, UInt32}(undef)
for ppid in 1:8
line = popfirst!(lines)
m = match(Regex("^PP$(ppid)_PLLLD = (0x[[:xdigit:]]+)\$"), line)
result_pp_pllds[ppid] = parse(UInt32, m[1])
end
AsdtpResult(
result_reconfig_done,
result_always_hit_flag,
result_autoreconfig,
result_asdtp_main,
result_asdtp_reset,
result_asdtp_total,
result_reconfig_done_2,
result_always_hit_flag_2,
result_si_done,
result_lolb_in,
result_ppconfig_done,
result_ppconfig_error,
result_pllld_fail_counter,
result_ppconfig_fail_counter,
result_pp_pllds,
)
end
"""
parse_qspip_section(lines::Base.Iterators.Stateful)
Parse Recov section of given stateful iterator of log.
# Args
- `lines`: Stateful iterator of slave log file lines
# Return
- `nothing`: if failed to parse
- `true`: if successed
- `false`
"""
function parse_recov_section!(lines::Base.Iterators.Stateful)
line = popfirst!(lines)
if startswith("====")(line)
line = popfirst!(lines)
end
m = match(r"Test Recov Result = (\d+)", line)
if isnothing(m)
return nothing
else
return m[1] == "1"
end
end
"""
parse_slavelog_file(filename::AbstractString)
Main function to parse slave log file.
"""
function parse_slavelog_file(filename::AbstractString)
lines_iter = Iterators.Stateful(eachline(filename))
asdtp_results = Any[]
mode::SlaveLogSection = MODE_NONE
# main loop
while !isempty(lines_iter)
# each sections
if mode == MODE_NONE
line = popfirst!(lines_iter)
mode = detect_mode_start(mode, line)
elseif mode == MODE_QSPIP
parse_qspip_section!(lines_iter)
mode = MODE_NONE
elseif mode == MODE_POWER
parse_power_section!(lines_iter)
mode = MODE_NONE
elseif mode == MODE_ASDTP
result = parse_asdtp_section!(lines_iter)
push!(asdtp_results, result)
mode = MODE_NONE
elseif mode == MODE_RECOV
parse_recov_section!(lines_iter)
mode = MODE_NONE
end
end
@info "Finished"
return asdtp_results
end
function eff99_count_map(asdtp_results)
# try(100) × channel(8) × channel(32)
@assert length(asdtp_results) == 100
@assert length(asdtp_results[begin]) == 8
@assert length(asdtp_results[begin][begin]) == 32
map(1:8) do i_asic
map(1:32) do i_channel
sum(1:100) do i_try
asdtp_results[i_try][i_asic][i_channel] != AsdtpMeasurement(0, 1, 0)
end
end
end
end
end