diff options
Diffstat (limited to 'icetime')
-rw-r--r-- | icetime/Makefile | 1 | ||||
-rw-r--r-- | icetime/icetime.cc | 271 |
2 files changed, 220 insertions, 52 deletions
diff --git a/icetime/Makefile b/icetime/Makefile index aead84a..2eef844 100644 --- a/icetime/Makefile +++ b/icetime/Makefile @@ -1,5 +1,4 @@ # CXX = clang -CXX ?= clang LDLIBS = -lm -lstdc++ CXXFLAGS = -MD -O0 -ggdb -Wall -std=c++11 -I/usr/local/include CC = $(CXX) diff --git a/icetime/icetime.cc b/icetime/icetime.cc index 61a63ed..f59ad12 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -32,10 +32,111 @@ struct net_segment_name }; std::map<net_segment_name, int> segment_to_net; -std::vector<std::set<net_segment_name>> net_to_segments; +std::map<int, std::set<net_segment_name>> net_to_segments; std::map<int, std::set<int>> net_buffers, net_rbuffers, net_routing; +std::map<std::pair<int, int>, std::pair<int, int>> connection_pos; std::set<int> used_nets; +// netlist_cells[cell_name][port_name] = port_expr +std::map<std::string, std::map<std::string, std::string>> netlist_cells; +std::map<std::string, std::string> netlist_cell_types; + +std::string vstringf(const char *fmt, va_list ap) +{ + std::string string; + char *str = NULL; + +#ifdef _WIN32 + int sz = 64, rc; + while (1) { + va_list apc; + va_copy(apc, ap); + str = (char*)realloc(str, sz); + rc = vsnprintf(str, sz, fmt, apc); + va_end(apc); + if (rc >= 0 && rc < sz) + break; + sz *= 2; + } +#else + if (vasprintf(&str, fmt, ap) < 0) + str = NULL; +#endif + + if (str != NULL) { + string = str; + free(str); + } + + return string; +} + +std::string stringf(const char *fmt, ...) +{ + std::string string; + va_list ap; + + va_start(ap, fmt); + string = vstringf(fmt, ap); + va_end(ap); + + return string; +} + +void read_config() +{ + char buffer[128]; + int tile_x, tile_y, line_nr = -1; + + while (fgets(buffer, 128, fin)) + { + if (buffer[0] == '.') + { + line_nr = -1; + const char *tok = strtok(buffer, " \t\r\n"); + + if (!strcmp(tok, ".device")) + { + config_device = strtok(nullptr, " \t\r\n"); + } else + if (!strcmp(tok, ".io_tile") || !strcmp(tok, ".logic_tile") || + !strcmp(tok, ".ramb_tile") || !strcmp(tok, ".ramt_tile")) + { + line_nr = 0; + tile_x = atoi(strtok(nullptr, " \t\r\n")); + tile_y = atoi(strtok(nullptr, " \t\r\n")); + + if (tile_x >= int(config_tile_type.size())) { + config_tile_type.resize(tile_x+1); + config_bits.resize(tile_x+1); + } + + if (tile_y >= int(config_tile_type.at(tile_x).size())) { + config_tile_type.at(tile_x).resize(tile_y+1); + config_bits.at(tile_x).resize(tile_y+1); + } + + if (!strcmp(tok, ".io_tile")) + config_tile_type.at(tile_x).at(tile_y) = "io"; + if (!strcmp(tok, ".logic_tile")) + config_tile_type.at(tile_x).at(tile_y) = "logic"; + if (!strcmp(tok, ".ramb_tile")) + config_tile_type.at(tile_x).at(tile_y) = "ramb"; + if (!strcmp(tok, ".ramt_tile")) + config_tile_type.at(tile_x).at(tile_y) = "ramt"; + } + } else + if (line_nr >= 0) + { + assert(int(config_bits.at(tile_x).at(tile_y).size()) == line_nr); + config_bits.at(tile_x).at(tile_y).resize(line_nr+1); + for (int i = 0; buffer[i] == '0' || buffer[i] == '1'; i++) + config_bits.at(tile_x).at(tile_y).at(line_nr).push_back(buffer[i] == '1'); + line_nr++; + } + } +} + void read_chipdb() { char buffer[1024]; @@ -50,6 +151,7 @@ void read_chipdb() std::string mode; int current_net = -1; + int tile_x = -1, tile_y = -1; std::string thiscfg; while (fgets(buffer, 1024, fdb)) @@ -68,14 +170,13 @@ void read_chipdb() if (mode == ".net") { current_net = atoi(strtok(nullptr, " \t\r\n")); - if (current_net >= int(net_to_segments.size())) - net_to_segments.resize(current_net+1); + continue; } if (mode == ".buffer" || mode == ".routing") { - int tile_x = atoi(strtok(nullptr, " \t\r\n")); - int tile_y = atoi(strtok(nullptr, " \t\r\n")); + tile_x = atoi(strtok(nullptr, " \t\r\n")); + tile_y = atoi(strtok(nullptr, " \t\r\n")); current_net = atoi(strtok(nullptr, " \t\r\n")); thiscfg = ""; @@ -85,6 +186,7 @@ void read_chipdb() assert(rc == 2); thiscfg.push_back(config_bits[tile_x][tile_y][bit_row][bit_col] ? '1' : '0'); } + continue; } continue; @@ -103,6 +205,9 @@ void read_chipdb() int other_net = atoi(strtok(nullptr, " \t\r\n")); net_rbuffers[current_net].insert(other_net); net_buffers[other_net].insert(current_net); + connection_pos[std::pair<int, int>(current_net, other_net)] = + connection_pos[std::pair<int, int>(other_net, current_net)] = + std::pair<int, int>(tile_x, tile_y); used_nets.insert(current_net); used_nets.insert(other_net); } @@ -111,65 +216,108 @@ void read_chipdb() int other_net = atoi(strtok(nullptr, " \t\r\n")); net_routing[current_net].insert(other_net); net_routing[other_net].insert(current_net); + connection_pos[std::pair<int, int>(current_net, other_net)] = + connection_pos[std::pair<int, int>(other_net, current_net)] = + std::pair<int, int>(tile_x, tile_y); used_nets.insert(current_net); used_nets.insert(other_net); } } fclose(fdb); -} -void read_config() -{ - char buffer[128]; - int tile_x, tile_y, line_nr = -1; + // purge unused nets from memory + int max_net = net_to_segments.rbegin()->first; + for (int net = 0; net <= max_net; net++) + { + if (used_nets.count(net)) + continue; - while (fgets(buffer, 128, fin)) + for (auto seg : net_to_segments[net]) + segment_to_net.erase(seg); + net_to_segments.erase(net); + + for (auto other : net_buffers[net]) + net_rbuffers[other].erase(net); + net_buffers.erase(net); + + for (auto other : net_rbuffers[net]) + net_buffers[other].erase(net); + net_rbuffers.erase(net); + + for (auto other : net_routing[net]) + net_routing[other].erase(net); + net_routing.erase(net); + } + +#if 1 + for (int net : used_nets) { - if (buffer[0] == '.') - { - line_nr = -1; - const char *tok = strtok(buffer, " \t\r\n"); + printf("// NET %d:\n", net); + for (auto seg : net_to_segments[net]) + printf("// SEG %d %d %s\n", seg.tile_x, seg.tile_y, seg.segment_name.c_str()); + for (auto other : net_buffers[net]) + printf("// BUFFER %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, + connection_pos[std::pair<int, int>(net, other)].second, other); + for (auto other : net_rbuffers[net]) + printf("// RBUFFER %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, + connection_pos[std::pair<int, int>(net, other)].second, other); + for (auto other : net_routing[net]) + printf("// ROUTE %d %d %d\n", connection_pos[std::pair<int, int>(net, other)].first, + connection_pos[std::pair<int, int>(net, other)].second, other); + } +#endif +} - if (!strcmp(tok, ".device")) - { - config_device = strtok(nullptr, " \t\r\n"); - } else - if (!strcmp(tok, ".io_tile") || !strcmp(tok, ".logic_tile") || - !strcmp(tok, ".ramb_tile") || !strcmp(tok, ".ramt_tile")) - { - line_nr = 0; - tile_x = atoi(strtok(nullptr, " \t\r\n")); - tile_y = atoi(strtok(nullptr, " \t\r\n")); +std::string make_seg_pre_io(int x, int y, int z) +{ + auto cell = stringf("pre_io_%d_%d_%d", x, y, z); + + if (netlist_cell_types.count(cell)) + return cell; + + netlist_cell_types[cell] = "PRE_IO"; + netlist_cells[cell]["PADIN"] = stringf("io_pad_%d_%d_%d_dout", x, y, z); + netlist_cells[cell]["PADOUT"] = stringf("io_pad_%d_%d_%d_din", x, y, z); + netlist_cells[cell]["PADOEN"] = stringf("io_pad_%d_%d_%d_oe", x, y, z); + netlist_cells[cell]["LATCHINPUTVALUE"] = ""; + netlist_cells[cell]["CLOCKENABLE"] = ""; + netlist_cells[cell]["INPUTCLK"] = ""; + netlist_cells[cell]["OUTPUTCLK"] = ""; + netlist_cells[cell]["OUTPUTENABLE"] = ""; + netlist_cells[cell]["DOUT1"] = ""; + netlist_cells[cell]["DOUT0"] = ""; + netlist_cells[cell]["DIN1"] = ""; + netlist_cells[cell]["DIN0"] = ""; + + fprintf(fout, " wire io_pad_%d_%d_%d_din;\n", x, y, z); + fprintf(fout, " wire io_pad_%d_%d_%d_dout;\n", x, y, z); + fprintf(fout, " wire io_pad_%d_%d_%d_oe;\n", x, y, z); + fprintf(fout, " (* keep *) wire io_pad_%d_%d_%d_pin;\n", x, y, z); + fprintf(fout, " IO_PAD io_pad_%d_%d_%d (\n", x, y, z); + fprintf(fout, " .DIN(io_pad_%d_%d_%d_din),\n", x, y, z); + fprintf(fout, " .DOUT(io_pad_%d_%d_%d_dout),\n", x, y, z); + fprintf(fout, " .OE(io_pad_%d_%d_%d_oe),\n", x, y, z); + fprintf(fout, " .PACKAGEPIN(io_pad_%d_%d_%d_pin)\n", x, y, z); + fprintf(fout, " );\n"); + + return cell; +} - if (tile_x >= int(config_tile_type.size())) { - config_tile_type.resize(tile_x+1); - config_bits.resize(tile_x+1); - } +void make_seg_cell(int net, const net_segment_name &seg) +{ + int a, b; - if (tile_y >= int(config_tile_type.at(tile_x).size())) { - config_tile_type.at(tile_x).resize(tile_y+1); - config_bits.at(tile_x).resize(tile_y+1); - } + if (sscanf(seg.segment_name.c_str(), "io_%d/D_IN_%d", &a, &b) == 2) { + auto cell = make_seg_pre_io(seg.tile_x, seg.tile_y, a); + netlist_cells[cell][stringf("DIN%d", b)] = stringf("net_%d", net); + return; + } - if (!strcmp(tok, ".io_tile")) - config_tile_type.at(tile_x).at(tile_y) = "io"; - if (!strcmp(tok, ".logic_tile")) - config_tile_type.at(tile_x).at(tile_y) = "logic"; - if (!strcmp(tok, ".ramb_tile")) - config_tile_type.at(tile_x).at(tile_y) = "ramb"; - if (!strcmp(tok, ".ramt_tile")) - config_tile_type.at(tile_x).at(tile_y) = "ramt"; - } - } else - if (line_nr >= 0) - { - assert(int(config_bits.at(tile_x).at(tile_y).size()) == line_nr); - config_bits.at(tile_x).at(tile_y).resize(line_nr+1); - for (int i = 0; buffer[i] == '0' || buffer[i] == '1'; i++) - config_bits.at(tile_x).at(tile_y).at(line_nr).push_back(buffer[i] == '1'); - line_nr++; - } + if (sscanf(seg.segment_name.c_str(), "io_%d/D_OUT_%d", &a, &b) == 2) { + auto cell = make_seg_pre_io(seg.tile_x, seg.tile_y, a); + netlist_cells[cell][stringf("DOUT%d", b)] = stringf("net_%d", net); + return; } } @@ -221,5 +369,26 @@ int main(int argc, char **argv) printf("// Reading chipdb file..\n"); read_chipdb(); + fprintf(fout, "module chip;\n"); + + for (int net : used_nets) + fprintf(fout, " wire net_%d;\n", net); + + for (int net : used_nets) + for (auto seg : net_to_segments[net]) + make_seg_cell(net, seg); + + for (auto it : netlist_cell_types) { + const char *sep = ""; + fprintf(fout, " %s %s (", it.second.c_str(), it.first.c_str()); + for (auto port : netlist_cells[it.first]) { + fprintf(fout, "%s\n .%s(%s)", sep, port.first.c_str(), port.second.c_str()); + sep = ","; + } + fprintf(fout, "\n );\n"); + } + + fprintf(fout, "endmodule\n"); + return 0; } |