From 53034959f338c952f4cf905890e44aad2ba202ae Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 20 Jul 2018 13:27:21 +0200 Subject: Start adding bitstream reading for ice40 --- gui/designwidget.cc | 11 +--- ice40/bitstream.cc | 166 +++++++++++++++++++++++++++++++++++++++++----------- ice40/bitstream.h | 1 + ice40/main.cc | 8 +++ 4 files changed, 143 insertions(+), 43 deletions(-) diff --git a/gui/designwidget.cc b/gui/designwidget.cc index 4123bf30..d28b843b 100644 --- a/gui/designwidget.cc +++ b/gui/designwidget.cc @@ -334,16 +334,7 @@ void DesignWidget::newContext(Context *ctx) for (auto pip : nameToItem[2].toStdMap()) { pip_root->addChild(pip.second); } - - // Add nets to tree - nets_root = new QTreeWidgetItem(treeWidget); - nets_root->setText(0, "Nets"); - treeWidget->insertTopLevelItem(0, nets_root); - - // Add cells to tree - cells_root = new QTreeWidgetItem(treeWidget); - cells_root->setText(0, "Cells"); - treeWidget->insertTopLevelItem(0, cells_root); + updateTree(); } void DesignWidget::updateTree() diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc index c12fa90e..b0f6260d 100644 --- a/ice40/bitstream.cc +++ b/ice40/bitstream.cc @@ -157,6 +157,42 @@ void configure_extra_cell(chipconfig_t &config, const Context *ctx, CellInfo *ce } } +std::string tagTileType(TileType &tile) +{ + if (tile == TILE_NONE) + return ""; + switch (tile) { + case TILE_LOGIC: + return ".logic_tile"; + break; + case TILE_IO: + return ".io_tile"; + break; + case TILE_RAMB: + return ".ramb_tile"; + break; + case TILE_RAMT: + return ".ramt_tile"; + break; + case TILE_DSP0: + return ".dsp0_tile"; + break; + case TILE_DSP1: + return ".dsp1_tile"; + break; + case TILE_DSP2: + return ".dsp2_tile"; + break; + case TILE_DSP3: + return ".dsp3_tile"; + break; + case TILE_IPCON: + return ".ipcon_tile"; + break; + default: + NPNR_ASSERT(false); + } +} void write_asc(const Context *ctx, std::ostream &out) { // [y][x][row][col] @@ -443,39 +479,7 @@ void write_asc(const Context *ctx, std::ostream &out) for (int y = 0; y < ci.height; y++) { for (int x = 0; x < ci.width; x++) { TileType tile = tile_at(ctx, x, y); - if (tile == TILE_NONE) - continue; - switch (tile) { - case TILE_LOGIC: - out << ".logic_tile"; - break; - case TILE_IO: - out << ".io_tile"; - break; - case TILE_RAMB: - out << ".ramb_tile"; - break; - case TILE_RAMT: - out << ".ramt_tile"; - break; - case TILE_DSP0: - out << ".dsp0_tile"; - break; - case TILE_DSP1: - out << ".dsp1_tile"; - break; - case TILE_DSP2: - out << ".dsp2_tile"; - break; - case TILE_DSP3: - out << ".dsp3_tile"; - break; - case TILE_IPCON: - out << ".ipcon_tile"; - break; - default: - NPNR_ASSERT(false); - } + out << tagTileType(tile); out << " " << x << " " << y << std::endl; for (auto row : config.at(y).at(x)) { for (auto col : row) { @@ -526,4 +530,100 @@ void write_asc(const Context *ctx, std::ostream &out) } } +void read_config(Context *ctx, std::istream &in, chipconfig_t &config) +{ + constexpr size_t line_buf_size = 65536; + char buffer[line_buf_size]; + int tile_x = -1, tile_y = -1, line_nr = -1; + + while (1) { + in.getline(buffer, line_buf_size); + if (buffer[0] == '.') { + line_nr = -1; + const char *tok = strtok(buffer, " \t\r\n"); + + if (!strcmp(tok, ".device")) { + std::string config_device = strtok(nullptr, " \t\r\n"); + std::string expected; + switch (ctx->args.type) { + case ArchArgs::LP384: + expected = "384"; + break; + case ArchArgs::HX1K: + case ArchArgs::LP1K: + expected = "1k"; + break; + case ArchArgs::HX8K: + case ArchArgs::LP8K: + expected = "8k"; + break; + case ArchArgs::UP5K: + expected = "5k"; + break; + default: + log_error("unsupported device type"); + } + if (expected != config_device) + log_error("device type does not match"); + } else if (!strcmp(tok, ".io_tile") || !strcmp(tok, ".logic_tile") || !strcmp(tok, ".ramb_tile") || + !strcmp(tok, ".ramt_tile") || !strcmp(tok, ".ipcon_tile") || !strcmp(tok, ".dsp0_tile") || + !strcmp(tok, ".dsp1_tile") || !strcmp(tok, ".dsp2_tile") || !strcmp(tok, ".dsp3_tile")) { + line_nr = 0; + tile_x = atoi(strtok(nullptr, " \t\r\n")); + tile_y = atoi(strtok(nullptr, " \t\r\n")); + + TileType tile = tile_at(ctx, tile_x, tile_y); + if (tok != tagTileType(tile)) + log_error("Wrong tile type for specified position"); + + } else if (!strcmp(tok, ".extra_bit")) { + /* + int b = atoi(strtok(nullptr, " \t\r\n")); + int x = atoi(strtok(nullptr, " \t\r\n")); + int y = atoi(strtok(nullptr, " \t\r\n")); + std::tuple key(b, x, y); + extra_bits.insert(key); + */ + } else if (!strcmp(tok, ".sym")) { + int net = atoi(strtok(nullptr, " \t\r\n")); (void)net; + const char *name = strtok(nullptr, " \t\r\n"); + std::unique_ptr created_net = std::unique_ptr(new NetInfo); + created_net->name = ctx->id(name); + ctx->nets[created_net->name] = std::move(created_net); + } + } else if (line_nr >= 0 && strlen(buffer) > 0) { + if (line_nr > int(config.at(tile_y).at(tile_x).size() - 1)) + log_error("Invalid data in input asc file"); + for (int i = 0; buffer[i] == '0' || buffer[i] == '1'; i++) + config.at(tile_y).at(tile_x).at(line_nr).at(i) = (buffer[i] == '1') ? 1 : 0; + line_nr++; + } + if (in.eof()) + break; + } +} + +bool read_asc(Context *ctx, std::istream &in) +{ + try { + // [y][x][row][col] + const ChipInfoPOD &ci = *ctx->chip_info; + const BitstreamInfoPOD &bi = *ci.bits_info; + chipconfig_t config; + config.resize(ci.height); + for (int y = 0; y < ci.height; y++) { + config.at(y).resize(ci.width); + for (int x = 0; x < ci.width; x++) { + TileType tile = tile_at(ctx, x, y); + int rows = bi.tiles_nonrouting[tile].rows; + int cols = bi.tiles_nonrouting[tile].cols; + config.at(y).at(x).resize(rows, std::vector(cols)); + } + } + read_config(ctx, in, config); + return true; + } catch (log_execution_error_exception) { + return false; + } +} NEXTPNR_NAMESPACE_END diff --git a/ice40/bitstream.h b/ice40/bitstream.h index 2b6cda1d..41a2ae68 100644 --- a/ice40/bitstream.h +++ b/ice40/bitstream.h @@ -27,6 +27,7 @@ NEXTPNR_NAMESPACE_BEGIN void write_asc(const Context *ctx, std::ostream &out); +bool read_asc(Context *ctx, std::istream &in); NEXTPNR_NAMESPACE_END diff --git a/ice40/main.cc b/ice40/main.cc index e77bdd34..c14b6086 100644 --- a/ice40/main.cc +++ b/ice40/main.cc @@ -95,6 +95,7 @@ int main(int argc, char *argv[]) options.add_options()("json", po::value(), "JSON design file to ingest"); options.add_options()("pcf", po::value(), "PCF constraints file to ingest"); options.add_options()("asc", po::value(), "asc bitstream file to write"); + options.add_options()("read", po::value(), "asc bitstream file to read"); options.add_options()("seed", po::value(), "seed value for random number generator"); options.add_options()("version,V", "show version"); options.add_options()("tmfuzz", "run path delay estimate fuzzer"); @@ -353,6 +354,13 @@ int main(int argc, char *argv[]) if (vm.count("no-tmdriv")) ctx->timing_driven = false; + if (vm.count("read")) { + std::string filename = vm["read"].as(); + std::ifstream f(filename); + if (!read_asc(ctx.get(), f)) + log_error("Loading ASC failed.\n"); + } + #ifndef NO_GUI if (vm.count("gui")) { Application a(argc, argv); -- cgit v1.2.3