blob: 7472bcbf3c1cbfdb129530bd5be2e0b7de122798 [file] [log] [blame]
#include "ChipConfig.hpp"
#include "Chip.hpp"
#include "BitDatabase.hpp"
#include "Database.hpp"
#include "Tile.hpp"
#include <sstream>
#include <iostream>
namespace Trellis {
string ChipConfig::to_string() const
{
stringstream ss;
ss << ".device " << chip_name << endl << endl;
for (const auto &meta : metadata)
ss << ".comment " << meta << endl;
for (const auto &sc : sysconfig)
ss << ".sysconfig " << sc.first << " " << sc.second << endl;
ss << endl;
for (const auto &tile : tiles) {
if (!tile.second.empty()) {
ss << ".tile " << tile.first << endl;
ss << tile.second;
ss << endl;
}
}
for (const auto &bram : bram_data) {
ss << ".bram_init " << bram.first << endl;
ios_base::fmtflags f( ss.flags() );
for (size_t i = 0; i < bram.second.size(); i++) {
ss << setw(3) << setfill('0') << hex << bram.second.at(i);
if (i % 8 == 7)
ss << endl;
else
ss << " ";
}
ss.flags(f);
ss << endl;
}
for (const auto &tg : tilegroups) {
ss << ".tile_group";
for (const auto &tile : tg.tiles) {
ss << " " << tile;
}
ss << endl;
ss << tg.config;
ss << endl;
}
return ss.str();
}
ChipConfig ChipConfig::from_string(const string &config)
{
stringstream ss(config);
ChipConfig cc;
while (!skip_check_eof(ss)) {
std::string verb;
ss >> verb;
if (verb == ".device") {
ss >> cc.chip_name;
} else if (verb == ".comment") {
std::string line;
ss.get(); //skip space
getline(ss, line);
cc.metadata.push_back(line);
} else if (verb == ".tile") {
std::string tilename;
ss >> tilename;
TileConfig tc;
ss >> tc;
cc.tiles[tilename] = tc;
} else if (verb == ".sysconfig") {
std::string key, value;
ss >> key >> value;
cc.sysconfig[key] = value;
} else if (verb == ".bram_init") {
uint16_t bram;
ss >> bram;
ios_base::fmtflags f(ss.flags());
while (!skip_check_eor(ss)) {
uint16_t value;
ss >> hex >> value;
cc.bram_data[bram].push_back(value);
}
ss.flags(f);
} else if (verb == ".tile_group") {
TileGroup tg;
std::string line;
getline(ss, line);
std::stringstream ss2(line);
std::string tile;
while (ss2) {
ss2 >> tile;
tg.tiles.push_back(tile);
}
ss >> tg.config;
cc.tilegroups.push_back(tg);
} else {
throw runtime_error("unrecognised config entry " + verb);
}
}
return cc;
}
Chip ChipConfig::to_chip() const
{
Chip c(chip_name);
c.metadata = metadata;
c.bram_data = bram_data;
set<string> processed_tiles;
for (auto tile_entry : c.tiles) {
auto tile_db = get_tile_bitdata(TileLocator{c.info.family, c.info.name, tile_entry.second->info.type});
if (tiles.find(tile_entry.first) != tiles.end()) {
tile_db->config_to_tile_cram(tiles.at(tile_entry.first), tile_entry.second->cram);
} else {
// Empty config sets default values (not always zero, e.g. in IO tiles)
tile_db->config_to_tile_cram(TileConfig(), tile_entry.second->cram);
}
processed_tiles.insert(tile_entry.first);
}
for (const auto &tilegroup : tilegroups) {
set<string> matched;
for (const auto &tilename : tilegroup.tiles) {
auto tile = c.tiles.at(tilename);
auto tile_db = get_tile_bitdata(TileLocator{c.info.family, c.info.name, tile->info.type});
tile_db->config_to_tile_cram(tilegroup.config, tile->cram, true, &matched);
}
for (const auto &word : tilegroup.config.cwords)
if (!matched.count(word.name))
throw runtime_error("config word " + word.name + " matched in no tilegroup tiles");
for (const auto &cenum : tilegroup.config.cenums)
if (!matched.count(cenum.name))
throw runtime_error("config enum " + cenum.name + " matched in no tilegroup tiles");
}
for (auto &tile : tiles) {
if (!processed_tiles.count(tile.first)) {
throw runtime_error("tile " + tile.first + " does not exist in chip " + chip_name);
}
}
return c;
}
ChipConfig ChipConfig::from_chip(const Chip &chip)
{
ChipConfig cc;
cc.chip_name = chip.info.name;
cc.metadata = chip.metadata;
cc.bram_data = chip.bram_data;
for (auto tile : chip.tiles) {
auto tile_db = get_tile_bitdata(TileLocator{chip.info.family, chip.info.name, tile.second->info.type});
cc.tiles[tile.first] = tile_db->tile_cram_to_config(tile.second->cram);
}
return cc;
}
}