| // Copyright 2020 Project U-Ray Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <vector> | |
| #include <iostream> | |
| #include <map> | |
| #include <string> | |
| #include <fstream> | |
| #include <stdexcept> | |
| #include <iterator> | |
| #include <stdarg.h> | |
| #include <iomanip> | |
| #include <filesystem> | |
| #include <map> | |
| #include <set> | |
| #include <cassert> | |
| #include "common.h" | |
| ChipData chip; | |
| struct Tile { | |
| std::string name, type; | |
| TileInstance *data; | |
| std::set<int> set_bits; | |
| std::set<int> unknown_bits; | |
| std::set<std::string> matched_features; | |
| }; | |
| std::vector<Tile> tiles; | |
| std::unordered_map<std::string, int> tile_by_name; | |
| struct InverseTileBitMap { | |
| int tile; | |
| int offset_in_frame; | |
| int offset_in_tile; | |
| int size; | |
| }; | |
| std::unordered_map<uint32_t, std::vector<InverseTileBitMap>> tiles_by_frame; | |
| void parse_bits(const std::string &filename) { | |
| LineReader rd(filename); | |
| for (auto &line : rd) { | |
| assert(line.at(0) == 'F'); | |
| const char *curr = line.c_str() + 1; | |
| char *next = nullptr; | |
| uint32_t frame = std::strtoul(curr, &next, 16); | |
| assert(*next == 'W'); | |
| curr = next + 1; | |
| int word = std::strtol(curr, &next, 10); | |
| curr = next + 1; | |
| assert(*next == 'B'); | |
| int bit = std::strtol(curr, &next, 10); | |
| if (tiles_by_frame.count(frame)) { | |
| int fb = word * 32 + bit; | |
| for (auto &t : tiles_by_frame.at(frame)) { | |
| if (fb >= t.offset_in_frame && fb < (t.offset_in_frame + t.size)) { | |
| int tilebit = (fb - t.offset_in_frame) + t.offset_in_tile; | |
| tiles[t.tile].set_bits.insert(tilebit); | |
| tiles[t.tile].unknown_bits.insert(tilebit); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // Currently have poor quality DBs for these tiles, | |
| // skip outputting them | |
| std::set<std::string> skip_tiles = { | |
| "CLEL_L", "CLEM_R", "RCLK_INT_R", | |
| }; | |
| void setup_tiles() { | |
| for (auto &tile : chip.tiles) { | |
| auto &ti = tile.second; | |
| if (skip_tiles.count(chip.tiletypes[ti.type].type)) | |
| continue; | |
| Tile t; | |
| t.name = ti.name; | |
| t.type = chip.tiletypes[ti.type].type; | |
| t.data = &ti; | |
| tile_by_name[ti.name] = int(tiles.size()); | |
| int off = 0; | |
| for (auto &b : ti.bits) { | |
| tiles_by_frame[b.frame_offset].push_back(InverseTileBitMap{int(tiles.size()), b.bit_offset, off, b.size}); | |
| off += b.size; | |
| } | |
| tiles.push_back(t); | |
| } | |
| } | |
| void process_tile(Tile &t) { | |
| if (t.set_bits.empty()) | |
| return; | |
| auto &td = chip.load_tile_database(t.name); | |
| for (const auto &feat : td.features) { | |
| if (feat.second.empty()) | |
| continue; | |
| bool matched = true; | |
| for (auto bit : feat.second) | |
| if (!t.set_bits.count(bit)) { | |
| matched = false; | |
| break; | |
| } | |
| if (!matched) | |
| continue; | |
| t.matched_features.insert(feat.first); | |
| for (auto bit : feat.second) | |
| t.unknown_bits.erase(bit); | |
| } | |
| } | |
| int main(int argc, char *argv[]) { | |
| if (argc < 3) { | |
| std::cerr << "usage: explain dbdir/ bitstream.dump" << std::endl; | |
| return 2; | |
| } | |
| chip.open(argv[1]); | |
| setup_tiles(); | |
| parse_bits(argv[2]); | |
| for (auto &t : tiles) { | |
| process_tile(t); | |
| for (auto &f : t.matched_features) | |
| std::cout << t.name << "." << f << std::endl; | |
| for (auto b : t.unknown_bits) | |
| std::cout << t.name << ".?" << b << std::endl; | |
| if (!t.matched_features.empty() || !t.unknown_bits.empty()) | |
| std::cout << std::endl; | |
| } | |
| } |