Start adding bitstream reading for ice40
This commit is contained in:
parent
3bad9c26cf
commit
53034959f3
@ -334,16 +334,7 @@ void DesignWidget::newContext(Context *ctx)
|
|||||||
for (auto pip : nameToItem[2].toStdMap()) {
|
for (auto pip : nameToItem[2].toStdMap()) {
|
||||||
pip_root->addChild(pip.second);
|
pip_root->addChild(pip.second);
|
||||||
}
|
}
|
||||||
|
updateTree();
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesignWidget::updateTree()
|
void DesignWidget::updateTree()
|
||||||
|
@ -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)
|
void write_asc(const Context *ctx, std::ostream &out)
|
||||||
{
|
{
|
||||||
// [y][x][row][col]
|
// [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 y = 0; y < ci.height; y++) {
|
||||||
for (int x = 0; x < ci.width; x++) {
|
for (int x = 0; x < ci.width; x++) {
|
||||||
TileType tile = tile_at(ctx, x, y);
|
TileType tile = tile_at(ctx, x, y);
|
||||||
if (tile == TILE_NONE)
|
out << tagTileType(tile);
|
||||||
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 << " " << x << " " << y << std::endl;
|
out << " " << x << " " << y << std::endl;
|
||||||
for (auto row : config.at(y).at(x)) {
|
for (auto row : config.at(y).at(x)) {
|
||||||
for (auto col : row) {
|
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
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
void write_asc(const Context *ctx, std::ostream &out);
|
void write_asc(const Context *ctx, std::ostream &out);
|
||||||
|
bool read_asc(Context *ctx, std::istream &in);
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
@ -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()("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()("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()("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()("seed", po::value<int>(), "seed value for random number generator");
|
||||||
options.add_options()("version,V", "show version");
|
options.add_options()("version,V", "show version");
|
||||||
options.add_options()("tmfuzz", "run path delay estimate fuzzer");
|
options.add_options()("tmfuzz", "run path delay estimate fuzzer");
|
||||||
@ -353,6 +354,13 @@ int main(int argc, char *argv[])
|
|||||||
if (vm.count("no-tmdriv"))
|
if (vm.count("no-tmdriv"))
|
||||||
ctx->timing_driven = false;
|
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
|
#ifndef NO_GUI
|
||||||
if (vm.count("gui")) {
|
if (vm.count("gui")) {
|
||||||
Application a(argc, argv);
|
Application a(argc, argv);
|
||||||
|
Loading…
Reference in New Issue
Block a user