17ec681f3Smrg-- A script that compares a set of equivalent cmdstream captures from
27ec681f3Smrg-- various generations, looking for equivalencies between registers.
37ec681f3Smrg--
47ec681f3Smrg-- This would be run across a group of similar tests for various
57ec681f3Smrg-- generations, for example:
67ec681f3Smrg--
77ec681f3Smrg--   cffdump --script scripts/analyze.lua a320/quad-flat-*.rd a420/quad-flat-*.rd
87ec681f3Smrg--
97ec681f3Smrg-- This is done by comparing unique register values.  Ie. for each
107ec681f3Smrg-- generation, find the set of registers that have different values
117ec681f3Smrg-- between equivalent draw calls.
127ec681f3Smrg
137ec681f3Smrglocal posix = require "posix"
147ec681f3Smrg
157ec681f3Smrgio.write("Analyzing Data...\n")
167ec681f3Smrg
177ec681f3Smrg-- results - table structure:
187ec681f3Smrg-- * [gpuname] - gpu
197ec681f3Smrg--   * tests
207ec681f3Smrg--     * [testname] - current test
217ec681f3Smrg--       * draws
227ec681f3Smrg--         * [1..n] - the draws
237ec681f3Smrg--           * primtype - the primitive type
247ec681f3Smrg--           * regs - table of values for draw
257ec681f3Smrg--             * [regbase] - regval
267ec681f3Smrg--   * regvals - table of unique values across all draws
277ec681f3Smrg--     * [regbase]
287ec681f3Smrg--       * [regval] - list of test names
297ec681f3Smrg--         * [1..n] - testname "." didx
307ec681f3Smrglocal results = {}
317ec681f3Smrg
327ec681f3Smrglocal test = nil
337ec681f3Smrglocal gpuname = nil
347ec681f3Smrglocal testname = nil
357ec681f3Smrg
367ec681f3Smrg
377ec681f3Smrg-- srsly, no sparse table size() op?
387ec681f3Smrgfunction tblsz(tbl)
397ec681f3Smrg  local n = 0;
407ec681f3Smrg  for k,v in pairs(tbl) do
417ec681f3Smrg    n = n + 1
427ec681f3Smrg  end
437ec681f3Smrg  return n
447ec681f3Smrgend
457ec681f3Smrg
467ec681f3Smrg
477ec681f3Smrgfunction start_cmdstream(name)
487ec681f3Smrg  testname = posix.basename(name)
497ec681f3Smrg  gpuname = posix.basename(posix.dirname(name))
507ec681f3Smrg  --io.write("START: gpuname=" .. gpuname .. ", testname=" .. testname .. "\n");
517ec681f3Smrg  local gpu = results[gpuname]
527ec681f3Smrg  if gpu == nil then
537ec681f3Smrg    gpu = {["tests"] = {}, ["regvals"] = {}}
547ec681f3Smrg    results[gpuname] = gpu
557ec681f3Smrg  end
567ec681f3Smrg  test = {["draws"] = {}}
577ec681f3Smrg  gpu["tests"][testname] = test
587ec681f3Smrgend
597ec681f3Smrg
607ec681f3Smrgfunction draw(primtype, nindx)
617ec681f3Smrg  -- RECTLIST is only used internally.. we want to ignore it for
627ec681f3Smrg  -- now, although it could potentially be interesting to track
637ec681f3Smrg  -- these separately (separating clear/restore/resolve) just to
647ec681f3Smrg  -- figure out which registers are used for which..
657ec681f3Smrg  if primtype == "DI_PT_RECTLIST" then
667ec681f3Smrg    return
677ec681f3Smrg  end
687ec681f3Smrg  local regtbl = {}
697ec681f3Smrg  local draw = {["primtype"] = primtype, ["regs"] = regtbl}
707ec681f3Smrg  local didx = tblsz(test["draws"])
717ec681f3Smrg
727ec681f3Smrg  test["draws"][didx] = draw
737ec681f3Smrg
747ec681f3Smrg  -- populate current regs.  For now just consider ones that have
757ec681f3Smrg  -- been written.. maybe we need to make that configurable in
767ec681f3Smrg  -- case it filters out too many registers.
777ec681f3Smrg  for regbase=0,0xffff do
787ec681f3Smrg    if regs.written(regbase) ~= 0 then
797ec681f3Smrg      local regval = regs.val(regbase)
807ec681f3Smrg
817ec681f3Smrg      -- track reg vals per draw:
827ec681f3Smrg      regtbl[regbase] = regval
837ec681f3Smrg
847ec681f3Smrg      -- also track which reg vals appear in which tests:
857ec681f3Smrg      local uniq_regvals = results[gpuname]["regvals"][regbase]
867ec681f3Smrg      if uniq_regvals == nil then
877ec681f3Smrg        uniq_regvals = {}
887ec681f3Smrg        results[gpuname]["regvals"][regbase] = uniq_regvals;
897ec681f3Smrg      end
907ec681f3Smrg      local drawlist = uniq_regvals[regval]
917ec681f3Smrg      if drawlist == nil then
927ec681f3Smrg        drawlist = {}
937ec681f3Smrg        uniq_regvals[regval] = drawlist
947ec681f3Smrg      end
957ec681f3Smrg      table.insert(drawlist, testname .. "." .. didx)
967ec681f3Smrg    end
977ec681f3Smrg  end
987ec681f3Smrg
997ec681f3Smrg  -- TODO maybe we want to whitelist a few well known regs, for the
1007ec681f3Smrg  -- convenience of the code that runs at the end to analyze the data?
1017ec681f3Smrg  -- TODO also would be useful to somehow capture CP_SET_BIN..
1027ec681f3Smrg
1037ec681f3Smrgend
1047ec681f3Smrg
1057ec681f3Smrgfunction end_cmdstream()
1067ec681f3Smrg  test = nil
1077ec681f3Smrg  gpuname = nil
1087ec681f3Smrg  testname = nil
1097ec681f3Smrgend
1107ec681f3Smrg
1117ec681f3Smrgfunction print_draws(gpuname, gpu)
1127ec681f3Smrg  io.write("  " .. gpuname .. "\n")
1137ec681f3Smrg  for testname,test in pairs(gpu["tests"]) do
1147ec681f3Smrg    io.write("    " .. testname .. ", draws=" .. #test["draws"] .. "\n")
1157ec681f3Smrg    for didx,draw in pairs(test["draws"]) do
1167ec681f3Smrg      io.write("      " .. didx .. ": " .. draw["primtype"] .. "\n")
1177ec681f3Smrg    end
1187ec681f3Smrg  end
1197ec681f3Smrgend
1207ec681f3Smrg
1217ec681f3Smrg-- sort and concat a list of draw names to form a key which can be
1227ec681f3Smrg-- compared to other drawlists to check for equality
1237ec681f3Smrg-- TODO maybe we instead want a scheme that allows for some fuzzyness
1247ec681f3Smrg-- in the matching??
1257ec681f3Smrgfunction drawlistname(drawlist)
1267ec681f3Smrg  local name = nil
1277ec681f3Smrg  for idx,draw in pairs(drawlist) do
1287ec681f3Smrg    if name == nil then
1297ec681f3Smrg      name = draw
1307ec681f3Smrg    else
1317ec681f3Smrg      name = name .. ":" .. draw
1327ec681f3Smrg    end
1337ec681f3Smrg  end
1347ec681f3Smrg  return name
1357ec681f3Smrgend
1367ec681f3Smrg
1377ec681f3Smrglocal rnntbl = {}
1387ec681f3Smrg
1397ec681f3Smrgfunction dumpmatches(name)
1407ec681f3Smrg  for gpuname,gpu in pairs(results) do
1417ec681f3Smrg    local r = rnntbl[gpuname]
1427ec681f3Smrg    if r == nil then
1437ec681f3Smrg      io.write("loading rnn database: \n" .. gpuname)
1447ec681f3Smrg      r = rnn.init(gpuname)
1457ec681f3Smrg      rnntbl[gpuname] = r
1467ec681f3Smrg    end
1477ec681f3Smrg    for regbase,regvals in pairs(gpu["regvals"]) do
1487ec681f3Smrg      for regval,drawlist in pairs(regvals) do
1497ec681f3Smrg        local name2 = drawlistname(drawlist)
1507ec681f3Smrg        if name == name2 then
1517ec681f3Smrg          io.write(string.format("  %s:%s:\t%08x  %s\n",
1527ec681f3Smrg                                 gpuname, rnn.regname(r, regbase),
1537ec681f3Smrg                                 regval, rnn.regval(r, regbase, regval)))
1547ec681f3Smrg        end
1557ec681f3Smrg      end
1567ec681f3Smrg    end
1577ec681f3Smrg  end
1587ec681f3Smrgend
1597ec681f3Smrg
1607ec681f3Smrgfunction finish()
1617ec681f3Smrg  -- drawlistnames that we've already dumped:
1627ec681f3Smrg  local dumped = {}
1637ec681f3Smrg
1647ec681f3Smrg  for gpuname,gpu in pairs(results) do
1657ec681f3Smrg    -- print_draws(gpuname, gpu)
1667ec681f3Smrg    for regbase,regvals in pairs(gpu["regvals"]) do
1677ec681f3Smrg      for regval,drawlist in pairs(regvals) do
1687ec681f3Smrg        local name = drawlistname(drawlist)
1697ec681f3Smrg        if dumped[name] == nil then
1707ec681f3Smrg          io.write("\n" .. name .. ":\n")
1717ec681f3Smrg          dumpmatches(name)
1727ec681f3Smrg          dumped[name] = 1
1737ec681f3Smrg        end
1747ec681f3Smrg      end
1757ec681f3Smrg    end
1767ec681f3Smrg  end
1777ec681f3Smrgend
1787ec681f3Smrg
179