aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-10-24 19:10:43 +0200
committerClifford Wolf <clifford@clifford.at>2015-10-24 19:10:43 +0200
commitf266dbeaf8b81934179d5582057fcf15fa151122 (patch)
tree1b9118c0a3a59c8f96a3d755f2dacdcb461642a7
parentf4b7aca5208010ee7131c710e946d8cb56f97648 (diff)
downloadicestorm-f266dbeaf8b81934179d5582057fcf15fa151122.tar.gz
icestorm-f266dbeaf8b81934179d5582057fcf15fa151122.tar.bz2
icestorm-f266dbeaf8b81934179d5582057fcf15fa151122.zip
icetime progress
-rw-r--r--icetime/Makefile4
-rw-r--r--icetime/icetime.cc122
-rw-r--r--icetime/mktest.py27
3 files changed, 131 insertions, 22 deletions
diff --git a/icetime/Makefile b/icetime/Makefile
index 76e8e9b..7c170d9 100644
--- a/icetime/Makefile
+++ b/icetime/Makefile
@@ -28,8 +28,8 @@ run0 run1 run2 run3 run4 run5 run6 run7 run8 run9: icetime
./icetime -P tq144 -p $(subst run,test,$@).pcf $(subst run,test,$@).txt $(subst run,test,$@)_out.v
show0 show1 show2 show3 show4 show5 show6 show7 show8 show9:
- # yosys -p 'equiv_purge; opt_clean -purge; show' $(subst show,test,$@).il
- yosys -p 'equiv_mark; opt_clean -purge; show -color orange a:equiv_region!=0' $(subst show,test,$@).il
+ # yosys -p 'equiv_mark; opt_clean -purge; show -color orange a:equiv_region!=0' $(subst show,test,$@).il
+ yosys -p 'equiv_purge; opt_clean -purge; show' $(subst show,test,$@).il
test: test0 test1 test2 test3 test4 test5 test6 test7 test8 test9
diff --git a/icetime/icetime.cc b/icetime/icetime.cc
index f2d54cc..e6f1167 100644
--- a/icetime/icetime.cc
+++ b/icetime/icetime.cc
@@ -19,6 +19,7 @@ std::vector<std::vector<std::string>> config_tile_type;
std::vector<std::vector<std::vector<std::vector<bool>>>> config_bits;
std::map<std::tuple<int, int, int>, std::string> pin_pos;
std::map<std::string, std::string> pin_names;
+std::set<std::tuple<int, int, int>> extra_bits;
std::set<std::string> io_names;
struct net_segment_t
@@ -43,6 +44,7 @@ struct net_segment_t
std::set<net_segment_t> segments;
std::map<int, std::set<net_segment_t>> net_to_segments;
+std::map<std::tuple<int, int, std::string>, int> x_y_name_net;
std::map<std::tuple<int, int, int>, net_segment_t> x_y_net_segment;
std::map<int, std::set<int>> net_buffers, net_rbuffers, net_routing;
std::map<std::pair<int, int>, std::pair<int, int>> connection_pos;
@@ -191,6 +193,13 @@ void read_config()
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 (!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 (line_nr >= 0)
@@ -221,6 +230,10 @@ void read_chipdb()
int tile_x = -1, tile_y = -1;
std::string thiscfg;
+ std::vector<std::vector<int>> gbufin;
+ std::vector<std::vector<int>> gbufpin;
+ std::set<std::string> extrabitfunc;
+
while (fgets(buffer, 1024, fdb))
{
if (buffer[0] == '#')
@@ -279,6 +292,7 @@ void read_chipdb()
int tile_y = atoi(strtok(nullptr, " \t\r\n"));
std::string segment_name = strtok(nullptr, " \t\r\n");
net_segment_t seg(tile_x, tile_y, current_net, segment_name);
+ std::tuple<int, int, std::string> x_y_name(tile_x, tile_y, segment_name);
net_to_segments[current_net].insert(seg);
segments.insert(seg);
}
@@ -304,6 +318,27 @@ void read_chipdb()
used_nets.insert(current_net);
used_nets.insert(other_net);
}
+
+ if (mode == ".gbufin" || mode == ".gbufpin") {
+ std::vector<int> items;
+ while (tok != nullptr) {
+ items.push_back(atoi(tok));
+ tok = strtok(nullptr, " \t\r\n");
+ }
+ if (mode == ".gbufin")
+ gbufin.push_back(items);
+ else
+ gbufpin.push_back(items);
+ }
+
+ if (mode == ".extra_bits") {
+ 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);
+ if (extra_bits.count(key))
+ extrabitfunc.insert(tok);
+ }
}
fclose(fdb);
@@ -337,6 +372,34 @@ void read_chipdb()
std::tuple<int, int, int> key(seg.x, seg.y, seg.net);
x_y_net_segment[key] = seg;
}
+ for (auto seg : segments) {
+ std::tuple<int, int, std::string> key(seg.x, seg.y, seg.name);
+ x_y_name_net[key] = seg.net;
+ }
+
+ for (auto &it : gbufin)
+ {
+ int x = it[0], y = it[1], g = it[2];
+
+ std::tuple<int, int, std::string> fabout_x_y_name(x, y, "fabout");
+ std::tuple<int, int, std::string> glbl_x_y_name(x, y, stringf("glb_netwk_%d", g));
+
+ if (!x_y_name_net.count(fabout_x_y_name) || !x_y_name_net.count(glbl_x_y_name))
+ continue;
+
+ int fabout_net = x_y_name_net.at(fabout_x_y_name);
+ int glbl_net = x_y_name_net.at(glbl_x_y_name);
+
+ assert(used_nets.count(fabout_net));
+ assert(used_nets.count(glbl_net));
+
+ net_rbuffers[glbl_net].insert(fabout_net);
+ net_buffers[fabout_net].insert(glbl_net);
+ connection_pos[std::pair<int, int>(glbl_net, fabout_net)] =
+ connection_pos[std::pair<int, int>(fabout_net, glbl_net)] =
+ std::pair<int, int>(x, y);
+ }
+
#if 1
for (int net : used_nets)
@@ -469,18 +532,34 @@ void make_odrv(int x, int y, int src)
}
}
-void make_inmux(int x, int y, int dst)
+void make_inmux(int x, int y, int dst, std::string muxtype = "")
{
for (int src : net_rbuffers[dst])
{
+ std::tuple<int, int, int> key(x, y, src);
+ std::string src_name = x_y_net_segment.at(key).name;
+ int cascade_n = 0;
+
+ if (src_name.size() > 6) {
+ cascade_n = src_name[6] - '0';
+ src_name[6] = 'X';
+ }
+
+ if (src_name == "lutff_X/out") {
+ auto cell = make_lc40(x, y, cascade_n);
+ netlist_cells[cell]["ltout"] = net_name(dst);
+ continue;
+ }
+
auto cell = stringf("inmux_%d_%d_%d_%d", x, y, src, dst);
if (netlist_cell_types.count(cell))
continue;
- netlist_cell_types[cell] = config_tile_type[x][y] == "io" ? "IoInMux" : "InMux";
+ netlist_cell_types[cell] = muxtype.empty() ? (config_tile_type[x][y] == "io" ? "IoInMux" : "InMux") : muxtype;
netlist_cells[cell]["I"] = net_name(src);
netlist_cells[cell]["O"] = net_name(dst);
+
register_interconn_dst(x, y, src);
no_interconn_net.insert(dst);
}
@@ -520,12 +599,37 @@ void make_seg_cell(int net, const net_segment_t &seg)
return;
}
- if (sscanf(seg.name.c_str(), "lutff_%d/ou%c", &a, &c) == 2 && c == 't') {
+ if (sscanf(seg.name.c_str(), "lutff_%d/ou%c", &a, &c) == 2 && c == 't')
+ {
+ for (int dst_net : net_buffers.at(seg.net))
+ for (auto &dst_seg : net_to_segments.at(dst_net)) {
+ std::string n = dst_seg.name;
+ if (n.size() > 6) n[6] = 'X';
+ if (n != "lutff_X/in_2")
+ goto use_lcout;
+ }
+ return;
+
+ use_lcout:
auto cell = make_lc40(seg.x, seg.y, a);
netlist_cells[cell]["lcout"] = net_name(net);
make_odrv(seg.x, seg.y, net);
return;
}
+
+ if (seg.name == "lutff_global/clk")
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ std::tuple<int, int, std::string> key(seg.x, seg.y, stringf("lutff_%d/out", i));
+ if (x_y_name_net.count(key)) {
+ auto cell = make_lc40(seg.x, seg.y, i);
+ make_inmux(seg.x, seg.y, net, "ClkMux");
+ netlist_cells[cell]["clk"] = net_name(seg.net);
+ }
+ }
+ return;
+ }
}
struct make_interconn_worker_t
@@ -746,10 +850,14 @@ void make_interconn(const net_segment_t &src)
};
std::function<void(const net_segment_t&,int,bool)> print_seg_tree = [&] (const net_segment_t &seg, int indent, bool chain) {
printf("// %*sSEG_TREE %d %d %s %d\n", indent, chain ? "`" : "", seg.x, seg.y, seg.name.c_str(), seg.net);
- auto &children = worker.seg_tree.at(seg);
- bool child_chain = children.size() == 1;
- for (auto &child : children)
- print_seg_tree(child, child_chain ? (chain ? indent : indent+1) : indent+2, child_chain);
+ if (worker.seg_tree.count(seg)) {
+ auto &children = worker.seg_tree.at(seg);
+ bool child_chain = children.size() == 1;
+ for (auto &child : children)
+ print_seg_tree(child, child_chain ? (chain ? indent : indent+1) : indent+2, child_chain);
+ } else {
+ printf("// %*s DEAD_END (!)\n", indent, "");
+ }
};
print_net_tree(src.net, 2);
print_seg_tree(src, 2, false);
diff --git a/icetime/mktest.py b/icetime/mktest.py
index f11d239..a2a1e0c 100644
--- a/icetime/mktest.py
+++ b/icetime/mktest.py
@@ -11,22 +11,23 @@ pins = np.random.permutation("""
""".split())
with open("%s.v" % sys.argv[1], "w") as f:
- print("module top(input i0, i1, i2, i3, output o0, o1, o2, o3);", file=f)
- print(" assign o0 = i0 || i1 && i2;", file=f)
- print(" assign o1 = i1 || i2 && i3;", file=f)
- print(" assign o2 = i0 || i2 && i3;", file=f)
- print(" assign o3 = i0 || i1 && i3;", file=f)
+ print("module top(input clk, i0, i1, i2, i3, output o0, o1, o2, o3);", file=f)
+ print(" reg [15:0] din, dout;", file=f)
+ print(" always @(posedge clk) din <= {din, i3, i2, i1, i0};", file=f)
+ print(" always @(posedge clk) dout <= din + {din[7:0], din[15:8]};", file=f)
+ print(" assign {o3, o2, o1, o0} = dout >> din;", file=f)
print("endmodule", file=f)
with open("%s.pcf" % sys.argv[1], "w") as f:
- print("set_io i0 %s" % pins[0], file=f)
- print("set_io i1 %s" % pins[1], file=f)
- print("set_io i2 %s" % pins[2], file=f)
- print("set_io i3 %s" % pins[3], file=f)
- print("set_io o0 %s" % pins[4], file=f)
- print("set_io o1 %s" % pins[5], file=f)
- print("set_io o2 %s" % pins[6], file=f)
- print("set_io o3 %s" % pins[7], file=f)
+ print("set_io clk %s" % pins[0], file=f)
+ print("set_io i0 %s" % pins[1], file=f)
+ print("set_io i1 %s" % pins[2], file=f)
+ print("set_io i2 %s" % pins[3], file=f)
+ print("set_io i3 %s" % pins[4], file=f)
+ print("set_io o0 %s" % pins[5], file=f)
+ print("set_io o1 %s" % pins[6], file=f)
+ print("set_io o2 %s" % pins[7], file=f)
+ print("set_io o3 %s" % pins[8], file=f)
with open("%s.ys" % sys.argv[1], "w") as f:
print("echo on", file=f)