Start adding bitstream reading for ice40

This commit is contained in:
Miodrag Milanovic 2018-07-20 13:27:21 +02:00
parent 3bad9c26cf
commit 53034959f3
4 changed files with 143 additions and 43 deletions

View File

@ -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()

View File

@ -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<int, int, int> 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<NetInfo> created_net = std::unique_ptr<NetInfo>(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<int8_t>(cols));
}
}
read_config(ctx, in, config);
return true;
} catch (log_execution_error_exception) {
return false;
}
}
NEXTPNR_NAMESPACE_END

View File

@ -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

View File

@ -95,6 +95,7 @@ int main(int argc, char *argv[])
options.add_options()("json", po::value<std::string>(), "JSON design file to ingest");
options.add_options()("pcf", po::value<std::string>(), "PCF constraints file to ingest");
options.add_options()("asc", po::value<std::string>(), "asc bitstream file to write");
options.add_options()("read", po::value<std::string>(), "asc bitstream file to read");
options.add_options()("seed", po::value<int>(), "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::string>();
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);