Skip to content

Commit

Permalink
Remove IO buffers when fed by SB_IO
Browse files Browse the repository at this point in the history
Signed-off-by: David Shah <[email protected]>
  • Loading branch information
gatecat committed Jun 13, 2018
1 parent ddf549b commit a76f5c5
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 15 deletions.
33 changes: 24 additions & 9 deletions common/design_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#ifndef DESIGN_UTILS_H
#define DESIGN_UTILS_H

#include <algorithm>

NEXTPNR_NAMESPACE_BEGIN

/*
Expand All @@ -35,23 +37,36 @@ void replace_port(CellInfo *old_cell, IdString old_name, CellInfo *rep_cell,
// If a net drives a given port of a cell matching a predicate (in many
// cases more than one cell type, e.g. SB_DFFxx so a predicate is used), return
// the first instance of that cell (otherwise nullptr). If exclusive is set to
// true, then this cell must be the only load
// true, then this cell must be the only load. If ignore_cell is set, that cell
// is not considered
template <typename F1>
CellInfo *net_only_drives(NetInfo *net, F1 cell_pred, IdString port,
bool exclusive = false)
bool exclusive = false, CellInfo *exclude = nullptr)
{
if (net == nullptr)
return nullptr;
if (exclusive && (net->users.size() != 1)) {
return nullptr;
} else {
for (const auto &load : net->users) {
if (cell_pred(load.cell) && load.port == port) {
return load.cell;
if (exclusive) {
if (exclude == nullptr) {
if (net->users.size() != 1)
return nullptr;
} else {
if (net->users.size() > 2) {
return nullptr;
} else if (net->users.size() == 2) {
if (std::find_if(net->users.begin(), net->users.end(),
[exclude](const PortRef &ref) {
return ref.cell == exclude;
}) == net->users.end())
return nullptr;
}
}
return nullptr;
}
for (const auto &load : net->users) {
if (load.cell != exclude && cell_pred(load.cell) && load.port == port) {
return load.cell;
}
}
return nullptr;
}

// If a net is driven by a given port of a cell matching a predicate, return
Expand Down
16 changes: 11 additions & 5 deletions frontend/json/jsonparse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -693,12 +693,16 @@ static void insert_iobuf(Design *design, NetInfo *net, PortType type,
design->cells[iobuf->name] = iobuf;
}

void json_import_toplevel_port(Design *design, const string &modname, const string& portname, JsonNode *node) {
void json_import_toplevel_port(Design *design, const string &modname,
const string &portname, JsonNode *node)
{
JsonNode *dir_node = node->data_dict.at("direction");
JsonNode *nets_node = node->data_dict.at("bits");
json_import_ports(design, modname, "Top Level IO", portname, dir_node, nets_node, [design](PortType type, const std::string &name, NetInfo *net){
insert_iobuf(design, net, type, name);
});
json_import_ports(
design, modname, "Top Level IO", portname, dir_node, nets_node,
[design](PortType type, const std::string &name, NetInfo *net) {
insert_iobuf(design, net, type, name);
});
}

void json_import(Design *design, string modname, JsonNode *node)
Expand Down Expand Up @@ -738,7 +742,9 @@ void json_import(Design *design, string modname, JsonNode *node)

here = ports_parent->data_dict.at(
ports_parent->data_dict_keys[portid]);
json_import_toplevel_port(design, modname, ports_parent->data_dict_keys[portid], here);
json_import_toplevel_port(design, modname,
ports_parent->data_dict_keys[portid],
here);
}
}
check_all_nets_driven(design);
Expand Down
3 changes: 3 additions & 0 deletions ice40/cells.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ inline bool is_ff(const CellInfo *cell)
cell->type == "SB_DFFNESS" || cell->type == "SB_DFFNES";
}

// Return true if a cell is a SB_IO
inline bool is_sb_io(const CellInfo *cell) { return cell->type == "SB_IO"; }

// Convert a SB_LUT primitive to (part of) an ICESTORM_LC, swapping ports
// as needed. Set no_dff if a DFF is not being used, so that the output
// can be reconnected
Expand Down
59 changes: 59 additions & 0 deletions ice40/pack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,69 @@ static void pack_constants(Design *design)
}
}

static bool is_nextpnr_iob(CellInfo *cell)
{
return cell->type == "$nextpnr_ibuf" || cell->type == "$nextpnr_obuf" ||
cell->type == "$nextpnr_iobuf";
}

// Pack IO buffers
static void pack_io(Design *design)
{
std::unordered_set<IdString> packed_cells;
std::vector<CellInfo *> new_cells;

for (auto cell : design->cells) {
CellInfo *ci = cell.second;
if (is_nextpnr_iob(ci)) {
if (ci->type == "$nextpnr_ibuf" || ci->type == "$nextpnr_iobuf") {
CellInfo *sb = net_only_drives(ci->ports.at("O").net, is_sb_io,
"PACKAGE_PIN", true, ci);
if (sb != nullptr) {
// Trivial case, SB_IO used. Just destroy the net and the
// iobuf
packed_cells.insert(ci->name);
log_info("%s feeds SB_IO %s, removing %s %s.\n",
ci->name.c_str(), sb->name.c_str(),
ci->type.c_str(), ci->name.c_str());
NetInfo *net = sb->ports.at("PACKAGE_PIN").net;
if (net != nullptr) {
design->nets.erase(net->name);
sb->ports.at("PACKAGE_PIN").net = nullptr;
}
}
} else if (ci->type == "$nextpnr_obuf") {
CellInfo *sb = net_only_drives(ci->ports.at("I").net, is_sb_io,
"PACKAGE_PIN", true, ci);
if (sb != nullptr) {
// Trivial case, SB_IO used. Just destroy the net and the
// iobuf
packed_cells.insert(ci->name);
log_info("%s feeds SB_IO %s, removing %s %s.\n",
ci->name.c_str(), sb->name.c_str(),
ci->type.c_str(), ci->name.c_str());
NetInfo *net = sb->ports.at("PACKAGE_PIN").net;
if (net != nullptr) {
design->nets.erase(net->name);
sb->ports.at("PACKAGE_PIN").net = nullptr;
}
}
}
}
}
for (auto pcell : packed_cells) {
design->cells.erase(pcell);
}
for (auto ncell : new_cells) {
design->cells[ncell->name] = ncell;
}
}

// Main pack function
void pack_design(Design *design)
{
pack_constants(design);
pack_io(design);
pack_lut_lutffs(design);
pack_nonlut_ffs(design);
}
Expand Down
2 changes: 1 addition & 1 deletion ice40/pack_tests/io_wrapper.v
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ module io_wrapper(input clk_pin, cen_pin, rst_pin, ina_pin, inb_pin,
.PULLUP(1'b0),
.NEG_TRIGGER(1'b0)
) outd_iob (
.PACKAGE_PIN(outa_pin),
.PACKAGE_PIN(outd_pin),
.LATCH_INPUT_VALUE(),
.CLOCK_ENABLE(),
.INPUT_CLK(),
Expand Down

0 comments on commit a76f5c5

Please sign in to comment.