mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-25 02:20:33 +00:00
reading...
This commit is contained in:
@@ -283,8 +283,13 @@ local function stamp_event_fields(events)
|
||||
end
|
||||
|
||||
local shape = ident:match("^mac_format_([%w_]+)_color$")
|
||||
if shape then mac_format_shape = shape end
|
||||
if ident:match("^mac_gte_store_[%w_]+$") then is_gte_store = true end
|
||||
if shape then
|
||||
mac_format_shape = shape
|
||||
end
|
||||
if ident:match("^mac_gte_store_[%w_]+$")
|
||||
then
|
||||
is_gte_store = true
|
||||
end
|
||||
if ident == "mac_insert_ot_tag" or ident:match("^mac_insert_ot_tag_[%w_]+$") then
|
||||
is_ot_tag = true
|
||||
end
|
||||
@@ -537,14 +542,9 @@ local function sign_extend_i16(value)
|
||||
return value
|
||||
end
|
||||
|
||||
local function is_gpr_operand(operand)
|
||||
return type(operand) == "string" and operand:sub(1, 2) == "R_"
|
||||
end
|
||||
local function is_gpr_operand(operand) return type(operand) == "string" and operand:sub(1, 2) == "R_" end
|
||||
|
||||
local function is_tracked_gpr(operand)
|
||||
return is_gpr_operand(operand)
|
||||
or (type(operand) == "string" and operand:sub(1, 7) == "reguse:")
|
||||
end
|
||||
local function is_tracked_gpr(operand) return is_gpr_operand(operand) or (type(operand) == "string" and operand:sub(1, 7) == "reguse:") end
|
||||
|
||||
local function constant_for_operand(gpr_values, operand)
|
||||
if operand == "R_0" then return 0 end
|
||||
@@ -672,8 +672,7 @@ local function is_cop2_use(ident)
|
||||
return canonical:sub(1, 9) == "gte_cmdw_" or ident:sub(1, 4) == "gte_"
|
||||
end
|
||||
|
||||
local function append_cu2_finding(atom, event, forward, transition,
|
||||
gap, kind, confidence, message)
|
||||
local function append_cu2_finding(atom, event, forward, transition, gap, kind, confidence, message)
|
||||
local event_ident = event.encoder or event.ident or "?"
|
||||
local policy = duffle.CU2_TRANSITION_POLICY or {}
|
||||
local evidence = policy.evidence or {}
|
||||
@@ -706,8 +705,7 @@ end
|
||||
|
||||
-- Read `sys_mov_to_cop0(source, 12)` before applying any writes from the current event.
|
||||
-- A known source stages a target transition; an unknown source stages an ambiguity that is reported only if a later COP2 use reaches it.
|
||||
local function stage_cu2_transition(ev_ident, ev_args, ev_word, ev_line,
|
||||
ev_source, forward)
|
||||
local function stage_cu2_transition(ev_ident, ev_args, ev_word, ev_line, ev_source, forward)
|
||||
if ev_ident ~= "sys_mov_to_cop0" then return end
|
||||
local policy = duffle.CU2_TRANSITION_POLICY
|
||||
if not policy then return end
|
||||
@@ -776,8 +774,7 @@ local function consume_cu2_transition(atom, event, ev_word, forward)
|
||||
if target == "enabled" then
|
||||
forward.cu2_state = "enabled"
|
||||
else
|
||||
append_cu2_finding(atom, event, forward, transition, gap,
|
||||
"error", "exact",
|
||||
append_cu2_finding(atom, event, forward, transition, gap, "error", "exact",
|
||||
string.format("%s at line %d: COP2 unavailable after SR.CU2 was disabled"
|
||||
.. " (gap=%d, required=%d)",
|
||||
atom.name, event_line,
|
||||
@@ -851,8 +848,7 @@ local function analyze_hardware_relations(atom)
|
||||
forward.c2_ctrl_writes = forward.c2_ctrl_writes or {}
|
||||
local alias = ev_args[2]
|
||||
if type(alias) ~= "string" or not alias:match("^gte_cr_") then
|
||||
alias = tostring(ev.call_text or ""):match("gte_cr_[%w_]+")
|
||||
or tostring(ev.root_call_text or ""):match("gte_cr_[%w_]+")
|
||||
alias = tostring(ev.call_text or ""):match("gte_cr_[%w_]+") or tostring(ev.root_call_text or ""):match("gte_cr_[%w_]+")
|
||||
end
|
||||
local src = ev_args[1]
|
||||
if type(src) == "string" then src = src:match("[%w_]+") end
|
||||
@@ -902,7 +898,8 @@ local function analyze_hardware_relations(atom)
|
||||
and relation.consumer == "cop2_input"
|
||||
and relation.id ~= "mtc2_irgb_visibility"
|
||||
and relation.id ~= "lwc2_to_gte_command"
|
||||
and relation.id ~= "lwc2_to_other_consumer" then
|
||||
and relation.id ~= "lwc2_to_other_consumer"
|
||||
then
|
||||
required = 0
|
||||
end
|
||||
local unknown_visibility = relation.visibility and relation.visibility.kind == "unknown_consumer"
|
||||
@@ -1628,8 +1625,7 @@ local function check_mac_yield_uniformity(atom, pipe_ctx, findings)
|
||||
if ev.is_yield or ev.is_raw_yield_tail then return true end
|
||||
local ident = ev.encoder or ev.ident or ""
|
||||
if ident == "mac_yield" or ident == "mac_yield_tail" then return true end
|
||||
local lead = tostring(ev.call_text or ""):match("^([%w_]+)")
|
||||
or tostring(ev.root_call_text or ""):match("^([%w_]+)")
|
||||
local lead = tostring(ev.call_text or ""):match("^([%w_]+)") or tostring(ev.root_call_text or ""):match("^([%w_]+)")
|
||||
return lead == "mac_yield" or lead == "mac_yield_tail"
|
||||
end
|
||||
|
||||
@@ -1874,8 +1870,7 @@ local function check_yield_load_tail_pairing(atom, _pipe_ctx, findings)
|
||||
line = line_for(ev),
|
||||
check = "yield_load_tail_pairing",
|
||||
kind = "error",
|
||||
msg = string.format(
|
||||
"%s at line %d has `mac_yield_load()` at word %d but the previous event is `%s`, not a branch; and the next label is `%s`. `mac_yield_load()` must fill a branch BD-slot or sit between two `atom_label`s for the natural fall-through load."
|
||||
msg = string.format("%s at line %d has `mac_yield_load()` at word %d but the previous event is `%s`, not a branch; and the next label is `%s`. `mac_yield_load()` must fill a branch BD-slot or sit between two `atom_label`s for the natural fall-through load."
|
||||
, atom.name, line_for(ev), event_idx, prev_ident, next_ident),
|
||||
}
|
||||
end
|
||||
@@ -2858,8 +2853,7 @@ local function check_gte_cr_alias_writes(atom, pipe_ctx, findings)
|
||||
line = distinct[1].line,
|
||||
check = "gte_cr_alias_writes",
|
||||
kind = "warning",
|
||||
msg = string.format(
|
||||
"atom '%s' touches %d aliases that share C2[%d]: %s; verify the intent"
|
||||
msg = string.format("atom '%s' touches %d aliases that share C2[%d]: %s; verify the intent"
|
||||
, atom.name or "", #distinct, slot, table.concat(aliases, ", ")),
|
||||
}
|
||||
end
|
||||
@@ -2871,7 +2865,6 @@ end
|
||||
-- The bare macro encodes only the cmd field; the canonical libgte-2-pass shape uses `gte_cmdw_mvmva_c11_pass2_exact = 0x4A49E012` (gte.h:430).
|
||||
--
|
||||
-- Severity: info by default. Escalates to warning when `GTE_RT_DIAGONAL_STRICT=1` env var is set (CI / production builds).
|
||||
--
|
||||
-- The bare macro IS the right call for the canonical libgte outer-product convention, so this is an opt-out hint rather than a hard warning.
|
||||
local function check_rtdiagonal_completeness(atom, _pipe_ctx, findings)
|
||||
local tokens = atom.paths and atom.paths.tokens or {}
|
||||
@@ -2886,8 +2879,7 @@ local function check_rtdiagonal_completeness(atom, _pipe_ctx, findings)
|
||||
line = atom_body_token_source_line(atom, token, line_in_body),
|
||||
check = "rtdiagonal_completeness",
|
||||
kind = strict and "warning" or "info",
|
||||
msg = string.format(
|
||||
"atom '%s' uses the bare gte_cmdw_mvmva macro; "
|
||||
msg = string.format("atom '%s' uses the bare gte_cmdw_mvmva macro; "
|
||||
.. "the canonical libgte-2-pass shape is gte_cmdw_mvmva_c11_pass2_exact = 0x4A49E012 "
|
||||
.. "(gte.h:430). The bare macro does not encode RT23/RT31/RT32/RT33; "
|
||||
.. "for a full 3x3 matrix, use the dedicated literal or hand-build via enc_gte_*()."
|
||||
@@ -2899,10 +2891,8 @@ end
|
||||
|
||||
-- Check #N+2: gte_cr_TR_naming
|
||||
-- Fires one info per atom body when a `gte_cr_TR[XYZ]` alias is used.
|
||||
-- Translation-vector registers are the only 3-letter-suffix C2 aliases
|
||||
-- (`TRX/TRY/TRZ`); an agent who reads `TRX` might typo it as `RT_X` or
|
||||
-- `RTX0` and either get a compile error (best case) or a build that
|
||||
-- links but routes the `ctc2` write to the wrong C2 slot.
|
||||
-- Translation-vector registers are the only 3-letter-suffix C2 aliases (`TRX/TRY/TRZ`); an agent who reads `TRX` might typo it as `RT_X` or
|
||||
-- `RTX0` and either get a compile error (best case) or a build that links but routes the `ctc2` write to the wrong C2 slot.
|
||||
--
|
||||
-- Severity: info. The convention is correct; this is a documentation-pointer check.
|
||||
local function check_gte_cr_TR_naming(atom, _pipe_ctx, findings)
|
||||
@@ -2963,8 +2953,7 @@ local function check_gte_cr_alias_writes_xatom(src, pipe_ctx, findings)
|
||||
line = w.line,
|
||||
check = "gte_cr_alias_writes_xatom",
|
||||
kind = "warning",
|
||||
msg = string.format(
|
||||
"atom '%s' writes %s to C2[%d]; atom '%s' already wrote %s"
|
||||
msg = string.format("atom '%s' writes %s to C2[%d]; atom '%s' already wrote %s"
|
||||
, atom.name or "", w.alias, slot, prev.atom, prev.alias),
|
||||
}
|
||||
end
|
||||
@@ -3003,8 +2992,7 @@ local function emit_packed_finding(atom, writes, rel, findings)
|
||||
line = line,
|
||||
check = "gte_packed_writes",
|
||||
kind = "warning",
|
||||
msg = string.format(
|
||||
"atom '%s' writes %s before %s on packed C2[%d]"
|
||||
msg = string.format("atom '%s' writes %s before %s on packed C2[%d]"
|
||||
, atom.name or "", rel.second, rel.first, rel.slot),
|
||||
}
|
||||
end
|
||||
@@ -3075,8 +3063,7 @@ local function emit_ctc2_finding(atom, line, dest, findings)
|
||||
line = line or atom.line,
|
||||
check = "ctc2_chain_source_preservation",
|
||||
kind = "warning",
|
||||
msg = string.format(
|
||||
"atom '%s' reloads %s before a later ctc2 that still names it"
|
||||
msg = string.format("atom '%s' reloads %s before a later ctc2 that still names it"
|
||||
, atom.name or "", dest),
|
||||
}
|
||||
end
|
||||
@@ -3249,10 +3236,8 @@ local function check_immediate_field_width(atom, pipe_ctx, findings)
|
||||
kind = "error",
|
||||
atom = atom.name,
|
||||
line = ev_line,
|
||||
msg = string.format(
|
||||
"%s: immediate %d at arg %d overflows %d-bit %s field (valid %d..%d)",
|
||||
ev_ident, signed_value, rule.arg, width,
|
||||
"signed", lo, hi),
|
||||
msg = string.format("%s: immediate %d at arg %d overflows %d-bit %s field (valid %d..%d)"
|
||||
, ev_ident, signed_value, rule.arg, width, "signed", lo, hi),
|
||||
}
|
||||
end
|
||||
else
|
||||
@@ -3267,9 +3252,8 @@ local function check_immediate_field_width(atom, pipe_ctx, findings)
|
||||
kind = "warning",
|
||||
atom = atom.name,
|
||||
line = ev_line,
|
||||
msg = string.format(
|
||||
"%s: negative immediate %d at arg %d on unsigned %d-bit field (truncated to %d by IMM_MASK)",
|
||||
ev_ident, signed_value, rule.arg, width, low_bits),
|
||||
msg = string.format("%s: negative immediate %d at arg %d on unsigned %d-bit field (truncated to %d by IMM_MASK)"
|
||||
, ev_ident, signed_value, rule.arg, width, low_bits),
|
||||
}
|
||||
else
|
||||
findings[#findings + 1] = {
|
||||
@@ -3277,20 +3261,20 @@ local function check_immediate_field_width(atom, pipe_ctx, findings)
|
||||
kind = "error",
|
||||
atom = atom.name,
|
||||
line = ev_line,
|
||||
msg = string.format(
|
||||
"%s: immediate %d at arg %d overflows %d-bit unsigned field (valid 0..%d)",
|
||||
ev_ident, value, rule.arg, width, field_max),
|
||||
msg = string.format("%s: immediate %d at arg %d overflows %d-bit unsigned field (valid 0..%d)"
|
||||
, ev_ident, value, rule.arg, width, field_max),
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO(Ed): Review this, if its still being used it needs to be re-evaluated for the current tape runtime.
|
||||
local SCRATCH_GPRS = {
|
||||
R_T0 = true, R_T1 = true, R_T2 = true, R_T3 = true,
|
||||
R_AT = true, R_V0 = true, R_V1 = true,
|
||||
@@ -3331,7 +3315,7 @@ local function collect_gpr_traffic(atom)
|
||||
for _, arg in ipairs(args) do
|
||||
local g = arg_as_gpr(arg)
|
||||
if g then
|
||||
reads[g] = true
|
||||
reads [g] = true
|
||||
writes[g] = true
|
||||
end
|
||||
end
|
||||
@@ -3376,12 +3360,10 @@ local function check_atom_calls_inferred_traffic(atom, pipe_ctx, findings)
|
||||
if ident:sub(1, 4) == "mac_" then
|
||||
local bare = ident:sub(5)
|
||||
local idx = pipe_ctx.component_body_index and pipe_ctx.component_body_index[bare]
|
||||
local comp = (pipe_ctx.components_by_name or {})[bare]
|
||||
or (pipe_ctx.atoms_by_name or {})[bare]
|
||||
local body_toks = (idx and idx.body_tokens)
|
||||
or (comp and (comp.body_tokens or (comp.paths and comp.paths.tokens)))
|
||||
local comp = (pipe_ctx.components_by_name or {})[bare] or (pipe_ctx.atoms_by_name or {})[bare]
|
||||
local body_toks = (idx and idx.body_tokens) or (comp and (comp.body_tokens or (comp.paths and comp.paths.tokens)))
|
||||
local cr, cw = collect_gpr_traffic(body_toks)
|
||||
for k in pairs(cr) do reads[k] = true end
|
||||
for k in pairs(cr) do reads [k] = true end
|
||||
for k in pairs(cw) do writes[k] = true end
|
||||
end
|
||||
end
|
||||
@@ -3393,6 +3375,7 @@ local function check_atom_calls_inferred_traffic(atom, pipe_ctx, findings)
|
||||
for k in pairs(inferred) do
|
||||
if k == "R_0" then
|
||||
if declared[k] then out[k] = true end
|
||||
-- TODO(Ed): Review usage of this array, this may be outdated and not representattive of the current tape runtime.
|
||||
elseif SCRATCH_GPRS[k] then
|
||||
if declared[k] then out[k] = true end
|
||||
else
|
||||
@@ -3409,13 +3392,12 @@ local function check_atom_calls_inferred_traffic(atom, pipe_ctx, findings)
|
||||
line = info.info_line or atom.line,
|
||||
check = "atom_calls_inferred_traffic",
|
||||
kind = "warning",
|
||||
msg = string.format(
|
||||
"atom '%s' declared [%s]/[%s] != inferred [%s]/[%s]",
|
||||
atom.name,
|
||||
table.concat(gpr_set_keys(decl_r), ","),
|
||||
table.concat(gpr_set_keys(decl_w), ","),
|
||||
table.concat(gpr_set_keys(reads), ","),
|
||||
table.concat(gpr_set_keys(writes), ",")),
|
||||
msg = string.format("atom '%s' declared [%s]/[%s] != inferred [%s]/[%s]"
|
||||
, atom.name
|
||||
, table.concat(gpr_set_keys(decl_r), ",")
|
||||
, table.concat(gpr_set_keys(decl_w), ",")
|
||||
, table.concat(gpr_set_keys(reads), ",")
|
||||
, table.concat(gpr_set_keys(writes), ","))
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -3439,13 +3421,12 @@ local function check_component_self_consistency(src, pipe_ctx, findings)
|
||||
line = ai.info_line or atom.line,
|
||||
check = "component_self_consistency",
|
||||
kind = "warning",
|
||||
msg = string.format(
|
||||
"component '%s' atom_reads/atom_writes [%s]/[%s] != body [%s]/[%s]",
|
||||
name,
|
||||
table.concat(gpr_set_keys(decl_r), ","),
|
||||
table.concat(gpr_set_keys(decl_w), ","),
|
||||
table.concat(gpr_set_keys(reads), ","),
|
||||
table.concat(gpr_set_keys(writes), ",")),
|
||||
msg = string.format("component '%s' atom_reads/atom_writes [%s]/[%s] != body [%s]/[%s]"
|
||||
, name
|
||||
, table.concat(gpr_set_keys(decl_r), ",")
|
||||
, table.concat(gpr_set_keys(decl_w), ",")
|
||||
, table.concat(gpr_set_keys(reads), ",")
|
||||
, table.concat(gpr_set_keys(writes), ","))
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -3694,8 +3675,8 @@ local function validate(ctx, src, corpus_pipe_ctx)
|
||||
end
|
||||
summaries[#summaries + 1] = {
|
||||
line = 0,
|
||||
msg = string.format("cycles: path-aware min=%d max=%d across %d atoms; worst atom=%s (%d); best-case, no stalls; BD-slot nops absorbed into branch costs",
|
||||
total_min, total_max, #atoms, max_atom_name or "?", max_atom_cyc),
|
||||
msg = string.format("cycles: path-aware min=%d max=%d across %d atoms; worst atom=%s (%d); best-case, no stalls; BD-slot nops absorbed into branch costs"
|
||||
, total_min, total_max, #atoms, max_atom_name or "?", max_atom_cyc),
|
||||
}
|
||||
end
|
||||
|
||||
@@ -3757,11 +3738,11 @@ function M.run(ctx)
|
||||
a.source_path = src.path
|
||||
all_atoms[#all_atoms + 1] = a
|
||||
end
|
||||
for _, f in ipairs(result.findings) do all_findings[#all_findings + 1] = f end
|
||||
for _, f in ipairs(result.findings) do all_findings [#all_findings + 1] = f end
|
||||
for _, e in ipairs(result.errors) do dir_errors [#dir_errors + 1] = e end
|
||||
for _, w in ipairs(result.warnings) do dir_warnings [#dir_warnings + 1] = w end
|
||||
for _, i_ in ipairs(result.info) do dir_info [#dir_info + 1] = i_ end
|
||||
for _, s in ipairs(result.summaries or {}) do dir_summaries[#dir_summaries + 1] = s end
|
||||
for _, s in ipairs(result.summaries or {}) do dir_summaries [#dir_summaries + 1] = s end
|
||||
end
|
||||
|
||||
-- Stash per-module results on the corpus for `report.lua` to consume.
|
||||
|
||||
Reference in New Issue
Block a user