1bf215546Sopenharmony_ci-- A script that compares a set of equivalent cmdstream captures from
2bf215546Sopenharmony_ci-- various generations, looking for equivalencies between registers.
3bf215546Sopenharmony_ci--
4bf215546Sopenharmony_ci-- This would be run across a group of similar tests for various
5bf215546Sopenharmony_ci-- generations, for example:
6bf215546Sopenharmony_ci--
7bf215546Sopenharmony_ci--   cffdump --script scripts/analyze.lua a320/quad-flat-*.rd a420/quad-flat-*.rd
8bf215546Sopenharmony_ci--
9bf215546Sopenharmony_ci-- This is done by comparing unique register values.  Ie. for each
10bf215546Sopenharmony_ci-- generation, find the set of registers that have different values
11bf215546Sopenharmony_ci-- between equivalent draw calls.
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_cilocal posix = require "posix"
14bf215546Sopenharmony_ci
15bf215546Sopenharmony_ciio.write("Analyzing Data...\n")
16bf215546Sopenharmony_ci
17bf215546Sopenharmony_ci-- results - table structure:
18bf215546Sopenharmony_ci-- * [gpuname] - gpu
19bf215546Sopenharmony_ci--   * tests
20bf215546Sopenharmony_ci--     * [testname] - current test
21bf215546Sopenharmony_ci--       * draws
22bf215546Sopenharmony_ci--         * [1..n] - the draws
23bf215546Sopenharmony_ci--           * primtype - the primitive type
24bf215546Sopenharmony_ci--           * regs - table of values for draw
25bf215546Sopenharmony_ci--             * [regbase] - regval
26bf215546Sopenharmony_ci--   * regvals - table of unique values across all draws
27bf215546Sopenharmony_ci--     * [regbase]
28bf215546Sopenharmony_ci--       * [regval] - list of test names
29bf215546Sopenharmony_ci--         * [1..n] - testname "." didx
30bf215546Sopenharmony_cilocal results = {}
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cilocal test = nil
33bf215546Sopenharmony_cilocal gpuname = nil
34bf215546Sopenharmony_cilocal testname = nil
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci-- srsly, no sparse table size() op?
38bf215546Sopenharmony_cifunction tblsz(tbl)
39bf215546Sopenharmony_ci  local n = 0;
40bf215546Sopenharmony_ci  for k,v in pairs(tbl) do
41bf215546Sopenharmony_ci    n = n + 1
42bf215546Sopenharmony_ci  end
43bf215546Sopenharmony_ci  return n
44bf215546Sopenharmony_ciend
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_cifunction start_cmdstream(name)
48bf215546Sopenharmony_ci  testname = posix.basename(name)
49bf215546Sopenharmony_ci  gpuname = posix.basename(posix.dirname(name))
50bf215546Sopenharmony_ci  --io.write("START: gpuname=" .. gpuname .. ", testname=" .. testname .. "\n");
51bf215546Sopenharmony_ci  local gpu = results[gpuname]
52bf215546Sopenharmony_ci  if gpu == nil then
53bf215546Sopenharmony_ci    gpu = {["tests"] = {}, ["regvals"] = {}}
54bf215546Sopenharmony_ci    results[gpuname] = gpu
55bf215546Sopenharmony_ci  end
56bf215546Sopenharmony_ci  test = {["draws"] = {}}
57bf215546Sopenharmony_ci  gpu["tests"][testname] = test
58bf215546Sopenharmony_ciend
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_cifunction draw(primtype, nindx)
61bf215546Sopenharmony_ci  -- RECTLIST is only used internally.. we want to ignore it for
62bf215546Sopenharmony_ci  -- now, although it could potentially be interesting to track
63bf215546Sopenharmony_ci  -- these separately (separating clear/restore/resolve) just to
64bf215546Sopenharmony_ci  -- figure out which registers are used for which..
65bf215546Sopenharmony_ci  if primtype == "DI_PT_RECTLIST" then
66bf215546Sopenharmony_ci    return
67bf215546Sopenharmony_ci  end
68bf215546Sopenharmony_ci  local regtbl = {}
69bf215546Sopenharmony_ci  local draw = {["primtype"] = primtype, ["regs"] = regtbl}
70bf215546Sopenharmony_ci  local didx = tblsz(test["draws"])
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci  test["draws"][didx] = draw
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci  -- populate current regs.  For now just consider ones that have
75bf215546Sopenharmony_ci  -- been written.. maybe we need to make that configurable in
76bf215546Sopenharmony_ci  -- case it filters out too many registers.
77bf215546Sopenharmony_ci  for regbase=0,0xffff do
78bf215546Sopenharmony_ci    if regs.written(regbase) ~= 0 then
79bf215546Sopenharmony_ci      local regval = regs.val(regbase)
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci      -- track reg vals per draw:
82bf215546Sopenharmony_ci      regtbl[regbase] = regval
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci      -- also track which reg vals appear in which tests:
85bf215546Sopenharmony_ci      local uniq_regvals = results[gpuname]["regvals"][regbase]
86bf215546Sopenharmony_ci      if uniq_regvals == nil then
87bf215546Sopenharmony_ci        uniq_regvals = {}
88bf215546Sopenharmony_ci        results[gpuname]["regvals"][regbase] = uniq_regvals;
89bf215546Sopenharmony_ci      end
90bf215546Sopenharmony_ci      local drawlist = uniq_regvals[regval]
91bf215546Sopenharmony_ci      if drawlist == nil then
92bf215546Sopenharmony_ci        drawlist = {}
93bf215546Sopenharmony_ci        uniq_regvals[regval] = drawlist
94bf215546Sopenharmony_ci      end
95bf215546Sopenharmony_ci      table.insert(drawlist, testname .. "." .. didx)
96bf215546Sopenharmony_ci    end
97bf215546Sopenharmony_ci  end
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci  -- TODO maybe we want to whitelist a few well known regs, for the
100bf215546Sopenharmony_ci  -- convenience of the code that runs at the end to analyze the data?
101bf215546Sopenharmony_ci  -- TODO also would be useful to somehow capture CP_SET_BIN..
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ciend
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_cifunction end_cmdstream()
106bf215546Sopenharmony_ci  test = nil
107bf215546Sopenharmony_ci  gpuname = nil
108bf215546Sopenharmony_ci  testname = nil
109bf215546Sopenharmony_ciend
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_cifunction print_draws(gpuname, gpu)
112bf215546Sopenharmony_ci  io.write("  " .. gpuname .. "\n")
113bf215546Sopenharmony_ci  for testname,test in pairs(gpu["tests"]) do
114bf215546Sopenharmony_ci    io.write("    " .. testname .. ", draws=" .. #test["draws"] .. "\n")
115bf215546Sopenharmony_ci    for didx,draw in pairs(test["draws"]) do
116bf215546Sopenharmony_ci      io.write("      " .. didx .. ": " .. draw["primtype"] .. "\n")
117bf215546Sopenharmony_ci    end
118bf215546Sopenharmony_ci  end
119bf215546Sopenharmony_ciend
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci-- sort and concat a list of draw names to form a key which can be
122bf215546Sopenharmony_ci-- compared to other drawlists to check for equality
123bf215546Sopenharmony_ci-- TODO maybe we instead want a scheme that allows for some fuzzyness
124bf215546Sopenharmony_ci-- in the matching??
125bf215546Sopenharmony_cifunction drawlistname(drawlist)
126bf215546Sopenharmony_ci  local name = nil
127bf215546Sopenharmony_ci  for idx,draw in pairs(drawlist) do
128bf215546Sopenharmony_ci    if name == nil then
129bf215546Sopenharmony_ci      name = draw
130bf215546Sopenharmony_ci    else
131bf215546Sopenharmony_ci      name = name .. ":" .. draw
132bf215546Sopenharmony_ci    end
133bf215546Sopenharmony_ci  end
134bf215546Sopenharmony_ci  return name
135bf215546Sopenharmony_ciend
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_cilocal rnntbl = {}
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_cifunction dumpmatches(name)
140bf215546Sopenharmony_ci  for gpuname,gpu in pairs(results) do
141bf215546Sopenharmony_ci    local r = rnntbl[gpuname]
142bf215546Sopenharmony_ci    if r == nil then
143bf215546Sopenharmony_ci      io.write("loading rnn database: \n" .. gpuname)
144bf215546Sopenharmony_ci      r = rnn.init(gpuname)
145bf215546Sopenharmony_ci      rnntbl[gpuname] = r
146bf215546Sopenharmony_ci    end
147bf215546Sopenharmony_ci    for regbase,regvals in pairs(gpu["regvals"]) do
148bf215546Sopenharmony_ci      for regval,drawlist in pairs(regvals) do
149bf215546Sopenharmony_ci        local name2 = drawlistname(drawlist)
150bf215546Sopenharmony_ci        if name == name2 then
151bf215546Sopenharmony_ci          io.write(string.format("  %s:%s:\t%08x  %s\n",
152bf215546Sopenharmony_ci                                 gpuname, rnn.regname(r, regbase),
153bf215546Sopenharmony_ci                                 regval, rnn.regval(r, regbase, regval)))
154bf215546Sopenharmony_ci        end
155bf215546Sopenharmony_ci      end
156bf215546Sopenharmony_ci    end
157bf215546Sopenharmony_ci  end
158bf215546Sopenharmony_ciend
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_cifunction finish()
161bf215546Sopenharmony_ci  -- drawlistnames that we've already dumped:
162bf215546Sopenharmony_ci  local dumped = {}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci  for gpuname,gpu in pairs(results) do
165bf215546Sopenharmony_ci    -- print_draws(gpuname, gpu)
166bf215546Sopenharmony_ci    for regbase,regvals in pairs(gpu["regvals"]) do
167bf215546Sopenharmony_ci      for regval,drawlist in pairs(regvals) do
168bf215546Sopenharmony_ci        local name = drawlistname(drawlist)
169bf215546Sopenharmony_ci        if dumped[name] == nil then
170bf215546Sopenharmony_ci          io.write("\n" .. name .. ":\n")
171bf215546Sopenharmony_ci          dumpmatches(name)
172bf215546Sopenharmony_ci          dumped[name] = 1
173bf215546Sopenharmony_ci        end
174bf215546Sopenharmony_ci      end
175bf215546Sopenharmony_ci    end
176bf215546Sopenharmony_ci  end
177bf215546Sopenharmony_ciend
178bf215546Sopenharmony_ci
179