Progress in icetime

This commit is contained in:
Clifford Wolf 2015-10-20 00:00:11 +02:00
parent 1f4e4d7724
commit de5ed1fec6
2 changed files with 244 additions and 76 deletions

View File

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

View File

@ -32,91 +32,55 @@ 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;
void read_chipdb()
// 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)
{
char buffer[1024];
snprintf(buffer, 1024, "/usr/local/share/icebox/chipdb-%s.txt", config_device.c_str());
std::string string;
char *str = NULL;
FILE *fdb = fopen(buffer, "r");
if (fdb == nullptr) {
perror("Can't open chipdb file");
exit(1);
#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 mode;
int current_net = -1;
std::string thiscfg;
std::string stringf(const char *fmt, ...)
{
std::string string;
va_list ap;
while (fgets(buffer, 1024, fdb))
{
if (buffer[0] == '#')
continue;
va_start(ap, fmt);
string = vstringf(fmt, ap);
va_end(ap);
const char *tok = strtok(buffer, " \t\r\n");
if (tok == nullptr)
continue;
if (tok[0] == '.')
{
mode = tok;
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);
}
if (mode == ".buffer" || mode == ".routing")
{
int tile_x = atoi(strtok(nullptr, " \t\r\n"));
int tile_y = atoi(strtok(nullptr, " \t\r\n"));
current_net = atoi(strtok(nullptr, " \t\r\n"));
thiscfg = "";
while ((tok = strtok(nullptr, " \t\r\n")) != nullptr) {
int bit_row, bit_col, rc;
rc = sscanf(tok, "B%d[%d]", &bit_row, &bit_col);
assert(rc == 2);
thiscfg.push_back(config_bits[tile_x][tile_y][bit_row][bit_col] ? '1' : '0');
}
}
continue;
}
if (mode == ".net") {
int tile_x = atoi(tok);
int tile_y = atoi(strtok(nullptr, " \t\r\n"));
std::string segment_name = strtok(nullptr, " \t\r\n");
net_segment_name seg(tile_x, tile_y, segment_name);
segment_to_net[seg] = current_net;
net_to_segments[current_net].insert(seg);
}
if (mode == ".buffer" && !strcmp(tok, thiscfg.c_str())) {
int other_net = atoi(strtok(nullptr, " \t\r\n"));
net_rbuffers[current_net].insert(other_net);
net_buffers[other_net].insert(current_net);
used_nets.insert(current_net);
used_nets.insert(other_net);
}
if (mode == ".routing" && !strcmp(tok, thiscfg.c_str())) {
int other_net = atoi(strtok(nullptr, " \t\r\n"));
net_routing[current_net].insert(other_net);
net_routing[other_net].insert(current_net);
used_nets.insert(current_net);
used_nets.insert(other_net);
}
}
fclose(fdb);
return string;
}
void read_config()
@ -173,6 +137,190 @@ void read_config()
}
}
void read_chipdb()
{
char buffer[1024];
snprintf(buffer, 1024, "/usr/local/share/icebox/chipdb-%s.txt", config_device.c_str());
FILE *fdb = fopen(buffer, "r");
if (fdb == nullptr) {
perror("Can't open chipdb file");
exit(1);
}
std::string mode;
int current_net = -1;
int tile_x = -1, tile_y = -1;
std::string thiscfg;
while (fgets(buffer, 1024, fdb))
{
if (buffer[0] == '#')
continue;
const char *tok = strtok(buffer, " \t\r\n");
if (tok == nullptr)
continue;
if (tok[0] == '.')
{
mode = tok;
if (mode == ".net")
{
current_net = atoi(strtok(nullptr, " \t\r\n"));
continue;
}
if (mode == ".buffer" || mode == ".routing")
{
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 = "";
while ((tok = strtok(nullptr, " \t\r\n")) != nullptr) {
int bit_row, bit_col, rc;
rc = sscanf(tok, "B%d[%d]", &bit_row, &bit_col);
assert(rc == 2);
thiscfg.push_back(config_bits[tile_x][tile_y][bit_row][bit_col] ? '1' : '0');
}
continue;
}
continue;
}
if (mode == ".net") {
int tile_x = atoi(tok);
int tile_y = atoi(strtok(nullptr, " \t\r\n"));
std::string segment_name = strtok(nullptr, " \t\r\n");
net_segment_name seg(tile_x, tile_y, segment_name);
segment_to_net[seg] = current_net;
net_to_segments[current_net].insert(seg);
}
if (mode == ".buffer" && !strcmp(tok, thiscfg.c_str())) {
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);
}
if (mode == ".routing" && !strcmp(tok, thiscfg.c_str())) {
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);
// 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;
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)
{
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
}
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;
}
void make_seg_cell(int net, const net_segment_name &seg)
{
int a, b;
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 (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;
}
}
void help(const char *cmd)
{
printf("\n");
@ -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;
}