aboutsummaryrefslogtreecommitdiffstats
path: root/icetime/icetime.cc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-10-23 17:16:37 +0200
committerClifford Wolf <clifford@clifford.at>2015-10-23 17:16:37 +0200
commitd193e581d0b8dd26a53c4dcb19991cc9e7ef8f17 (patch)
tree407ef7da8f19d40790c29bb373593da43ff59393 /icetime/icetime.cc
parent647eedfc21317bd20de934ae6875e7a7a7f0ce8a (diff)
downloadicestorm-d193e581d0b8dd26a53c4dcb19991cc9e7ef8f17.tar.gz
icestorm-d193e581d0b8dd26a53c4dcb19991cc9e7ef8f17.tar.bz2
icestorm-d193e581d0b8dd26a53c4dcb19991cc9e7ef8f17.zip
Progress in icetime
Diffstat (limited to 'icetime/icetime.cc')
-rw-r--r--icetime/icetime.cc87
1 files changed, 66 insertions, 21 deletions
diff --git a/icetime/icetime.cc b/icetime/icetime.cc
index e21dafc..74426d0 100644
--- a/icetime/icetime.cc
+++ b/icetime/icetime.cc
@@ -50,11 +50,13 @@ std::set<int> used_nets;
std::set<net_segment_t> interconn_src, interconn_dst;
std::set<int> no_interconn_net;
+int iconn_cell_cnt = 0;
// 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::set<std::string> extra_wires;
std::vector<std::string> extra_vlog;
std::set<int> declared_nets;
@@ -106,6 +108,15 @@ std::string net_name(int net)
return stringf("net_%d", net);
}
+std::string seg_name(const net_segment_t &seg)
+{
+ std::string str = stringf("seg_%d_%d_%s_%d", seg.x, seg.y, seg.name.c_str(), seg.net);
+ for (auto &ch : str)
+ if (ch == '/') ch = '_';
+ extra_wires.insert(str);
+ return str;
+}
+
void read_pcf(const char *filename)
{
FILE *f = fopen(filename, "r");
@@ -514,7 +525,7 @@ struct make_interconn_worker_t
std::map<int, std::set<int>> net_tree;
std::map<net_segment_t, std::set<net_segment_t>> seg_tree;
std::map<net_segment_t, net_segment_t> seg_parents;
- std::set<net_segment_t> target_segs;
+ std::set<net_segment_t> target_segs, handled_segs;
void build_net_tree(int src)
{
@@ -617,35 +628,59 @@ struct make_interconn_worker_t
void create_cells(const net_segment_t &trg)
{
- if (seg_parents.count(trg) == 0)
+ if (handled_segs.count(trg))
+ return;
+
+ handled_segs.insert(trg);
+
+ if (seg_parents.count(trg) == 0) {
+ extra_vlog.push_back(stringf(" assign %s = %s;\n", seg_name(trg).c_str(), net_name(trg.net).c_str()));
return;
+ }
const net_segment_t *cursor = &seg_parents.at(trg);
+ // Local Mux
+
if (trg.name.substr(0, 6) == "local_")
{
- extra_vlog.push_back(stringf(" LocalMux conn_%d_%d (.I(%s), .O(%s));\n",
- cursor->net, trg.net, net_name(cursor->net).c_str(), net_name(trg.net).c_str()));
-
- declared_nets.insert(cursor->net);
- create_cells(*cursor);
- return;
+ extra_vlog.push_back(stringf(" LocalMux conn_%d (.I(%s), .O(%s));\n",
+ iconn_cell_cnt++, seg_name(*cursor).c_str(), seg_name(trg).c_str()));
+ goto continue_at_cursor;
}
- if (trg.name.substr(0, 6) == "span4_")
+ // Span4Mux
+
+ if (trg.name.substr(0, 6) == "span4_" || trg.name.substr(0, 4) == "sp4_")
{
- while (seg_parents.count(*cursor) && cursor->net == trg.net)
+ bool non_io = trg.name.substr(0, 4) == "sp4_";
+ bool horiz_non_io = trg.name.substr(0, 6) == "sp4_h_";
+ int count_length = -1;
+
+ while (seg_parents.count(*cursor) && cursor->net == trg.net) {
+ non_io = non_io || (cursor->name.substr(0, 4) == "sp4_");
+ horiz_non_io = horiz_non_io || (cursor->name.substr(0, 6) == "sp4_h_");
cursor = &seg_parents.at(*cursor);
+ count_length++;
+ }
if (cursor->net == trg.net)
- return;
+ goto skip_to_cursor;
- extra_vlog.push_back(stringf(" IoSpan4Mux conn_%d_%d (.I(%s), .O(%s));\n",
- cursor->net, trg.net, net_name(cursor->net).c_str(), net_name(trg.net).c_str()));
+ if (cursor->name.substr(0, 7) == "span12_" || cursor->name.substr(0, 5) == "sp12_") {
+ extra_vlog.push_back(stringf(" Sp12to4 conn_%d (.I(%s), .O(%s));\n",
+ iconn_cell_cnt++, seg_name(*cursor).c_str(), seg_name(trg).c_str()));
+ } else
+ if (non_io) {
+ extra_vlog.push_back(stringf(" Span4Mux_%c%d conn_%d (.I(%s), .O(%s));\n",
+ horiz_non_io ? 'h' : 'v', count_length, iconn_cell_cnt++,
+ seg_name(*cursor).c_str(), seg_name(trg).c_str()));
+ } else {
+ extra_vlog.push_back(stringf(" IoSpan4Mux conn_%d (.I(%s), .O(%s));\n",
+ iconn_cell_cnt++, seg_name(*cursor).c_str(), seg_name(trg).c_str()));
+ }
- declared_nets.insert(cursor->net);
- create_cells(*cursor);
- return;
+ goto continue_at_cursor;
}
// Default handler
@@ -654,11 +689,16 @@ struct make_interconn_worker_t
cursor = &seg_parents.at(*cursor);
if (cursor->net == trg.net)
- return;
+ goto skip_to_cursor;
+
+ extra_vlog.push_back(stringf(" INTERCONN conn_%d (.I(%s), .O(%s));\n",
+ iconn_cell_cnt++, seg_name(*cursor).c_str(), seg_name(trg).c_str()));
+ goto continue_at_cursor;
- extra_vlog.push_back(stringf(" INTERCONN conn_%d_%d (.I(%s), .O(%s));\n",
- cursor->net, trg.net, net_name(cursor->net).c_str(), net_name(trg.net).c_str()));
- declared_nets.insert(cursor->net);
+ skip_to_cursor:
+ extra_vlog.push_back(stringf(" assign %s = %s;\n", seg_name(trg).c_str(), seg_name(*cursor).c_str()));
+ continue_at_cursor:
+ create_cells(*cursor);
}
};
@@ -686,8 +726,10 @@ void make_interconn(const net_segment_t &src)
print_seg_tree(src, 2, false);
#endif
- for (auto &seg : worker.target_segs)
+ for (auto &seg : worker.target_segs) {
+ extra_vlog.push_back(stringf(" assign %s = %s;\n", net_name(seg.net).c_str(), seg_name(seg).c_str()));
worker.create_cells(seg);
+ }
}
void help(const char *cmd)
@@ -767,6 +809,9 @@ int main(int argc, char **argv)
for (int net : declared_nets)
fprintf(fout, " wire net_%d;\n", net);
+ for (auto net : extra_wires)
+ fprintf(fout, " wire %s;\n", net.c_str());
+
for (auto &str : extra_vlog)
fprintf(fout, "%s", str.c_str());