aboutsummaryrefslogtreecommitdiffstats
path: root/fpga_interchange/arch.cc
diff options
context:
space:
mode:
authorKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-19 17:28:25 -0800
committerKeith Rothman <537074+litghost@users.noreply.github.com>2021-02-23 14:09:28 -0800
commit5574455d2a20d3bb950e5dd907ef193d049a2a26 (patch)
tree575a82d63b89f61f0a6d96afd33f3bd804dcfad8 /fpga_interchange/arch.cc
parent2fc353d5592b0bf9ed8428545bbd6a64312cc16e (diff)
downloadnextpnr-5574455d2a20d3bb950e5dd907ef193d049a2a26.tar.gz
nextpnr-5574455d2a20d3bb950e5dd907ef193d049a2a26.tar.bz2
nextpnr-5574455d2a20d3bb950e5dd907ef193d049a2a26.zip
Working FF example now that constant merging is done.
Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
Diffstat (limited to 'fpga_interchange/arch.cc')
-rw-r--r--fpga_interchange/arch.cc187
1 files changed, 182 insertions, 5 deletions
diff --git a/fpga_interchange/arch.cc b/fpga_interchange/arch.cc
index 0955c376..966d74f3 100644
--- a/fpga_interchange/arch.cc
+++ b/fpga_interchange/arch.cc
@@ -606,6 +606,7 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
bool Arch::pack()
{
+ merge_constant_nets();
pack_ports();
return true;
}
@@ -754,7 +755,7 @@ const std::vector<std::string> Arch::availablePlacers = {"sa",
const std::string Arch::defaultRouter = "router2";
const std::vector<std::string> Arch::availableRouters = {"router1", "router2"};
-void Arch::map_cell_pins(CellInfo *cell, int32_t mapping) const
+void Arch::map_cell_pins(CellInfo *cell, int32_t mapping)
{
cell->cell_mapping = mapping;
cell->cell_bel_pins.clear();
@@ -766,11 +767,32 @@ void Arch::map_cell_pins(CellInfo *cell, int32_t mapping) const
IdString bel_pin(pin_map.bel_pin);
if (cell_pin.str(this) == "GND") {
- // FIXME: Tie this pin to the GND net
+ PortInfo port_info;
+ port_info.name = bel_pin;
+ port_info.type = PORT_IN;
+ port_info.net = nullptr;
+
+ auto result = cell->ports.emplace(bel_pin, port_info);
+ NPNR_ASSERT(result.second);
+
+ cell->cell_bel_pins[bel_pin].push_back(bel_pin);
+
+ connectPort(IdString(chip_info->constants->gnd_net_name), cell->name, bel_pin);
continue;
}
+
if (cell_pin.str(this) == "VCC") {
- // FIXME: Tie this pin to the VCC net
+ PortInfo port_info;
+ port_info.name = bel_pin;
+ port_info.type = PORT_IN;
+ port_info.net = nullptr;
+
+ auto result = cell->ports.emplace(bel_pin, port_info);
+ NPNR_ASSERT(result.second);
+
+ cell->cell_bel_pins[bel_pin].push_back(bel_pin);
+
+ connectPort(IdString(chip_info->constants->vcc_net_name), cell->name, bel_pin);
continue;
}
@@ -795,11 +817,30 @@ void Arch::map_cell_pins(CellInfo *cell, int32_t mapping) const
IdString bel_pin(pin_map.bel_pin);
if (cell_pin.str(this) == "GND") {
- // FIXME: Tie this pin to the GND net
+ PortInfo port_info;
+ port_info.name = bel_pin;
+ port_info.type = PORT_IN;
+
+ auto result = cell->ports.emplace(bel_pin, port_info);
+ NPNR_ASSERT(result.second);
+
+ cell->cell_bel_pins[bel_pin].push_back(bel_pin);
+
+ connectPort(IdString(chip_info->constants->gnd_net_name), cell->name, bel_pin);
continue;
}
+
if (cell_pin.str(this) == "VCC") {
- // FIXME: Tie this pin to the VCC net
+ PortInfo port_info;
+ port_info.name = bel_pin;
+ port_info.type = PORT_IN;
+
+ auto result = cell->ports.emplace(bel_pin, port_info);
+ NPNR_ASSERT(result.second);
+
+ cell->cell_bel_pins[bel_pin].push_back(bel_pin);
+
+ connectPort(IdString(chip_info->constants->vcc_net_name), cell->name, bel_pin);
continue;
}
@@ -858,6 +899,142 @@ size_t Arch::get_cell_type_index(IdString cell_type) const
return cell_offset;
}
+void Arch::merge_constant_nets() {
+ NetInfo* gnd_net = nullptr;
+ NetInfo* vcc_net = nullptr;
+
+ bool need_gnd_source = false;
+ bool need_vcc_source = false;
+
+ IdString gnd_net_name(chip_info->constants->gnd_net_name);
+ IdString gnd_cell_type(chip_info->constants->gnd_cell_name);
+ IdString gnd_cell_port(chip_info->constants->gnd_cell_port);
+
+ auto gnd_iter = nets.find(gnd_net_name);
+ if(gnd_iter != nets.end()) {
+ NPNR_ASSERT(gnd_iter->second->driver.cell != nullptr);
+ NPNR_ASSERT(gnd_iter->second->driver.cell->type == gnd_cell_type);
+ NPNR_ASSERT(gnd_iter->second->driver.port == gnd_cell_port);
+
+ gnd_net = gnd_iter->second.get();
+ } else {
+ gnd_net = createNet(gnd_net_name);
+ need_gnd_source = true;
+ }
+
+ IdString vcc_net_name(chip_info->constants->vcc_net_name);
+ IdString vcc_cell_type(chip_info->constants->vcc_cell_name);
+ IdString vcc_cell_port(chip_info->constants->vcc_cell_port);
+
+ auto vcc_iter = nets.find(vcc_net_name);
+ if(vcc_iter != nets.end()) {
+ NPNR_ASSERT(vcc_iter->second->driver.cell != nullptr);
+ NPNR_ASSERT(vcc_iter->second->driver.cell->type == vcc_cell_type);
+ NPNR_ASSERT(vcc_iter->second->driver.port == vcc_cell_port);
+
+ vcc_net = vcc_iter->second.get();
+ } else {
+ vcc_net = createNet(vcc_net_name);
+ need_vcc_source = true;
+ }
+
+ std::vector<IdString> other_gnd_nets;
+ std::vector<IdString> other_vcc_nets;
+
+ for(auto & net_pair : nets) {
+ if(net_pair.first == gnd_net_name) {
+ NPNR_ASSERT(net_pair.second.get() == gnd_net);
+ continue;
+ }
+
+ if(net_pair.first == vcc_net_name) {
+ NPNR_ASSERT(net_pair.second.get() == vcc_net);
+ continue;
+ }
+
+ NetInfo *net = net_pair.second.get();
+ if(net->driver.cell == nullptr) {
+ continue;
+ }
+
+ if(net->driver.cell->type == gnd_cell_type) {
+ NPNR_ASSERT(net->driver.port == gnd_cell_port);
+
+ other_gnd_nets.push_back(net_pair.first);
+
+ if(need_gnd_source) {
+ IdString driver_cell = net->driver.cell->name;
+ disconnectPort(driver_cell, gnd_cell_port);
+ connectPort(gnd_net_name, driver_cell, gnd_cell_port);
+ need_gnd_source = false;
+ }
+
+ NPNR_ASSERT(net->driver.port == gnd_cell_port);
+ std::vector<PortRef> users_copy = net->users;
+ for(const PortRef & port_ref : users_copy) {
+ IdString cell = port_ref.cell->name;
+ disconnectPort(cell, port_ref.port);
+ connectPort(gnd_net_name, cell, port_ref.port);
+ }
+ }
+
+ if(net->driver.cell->type == vcc_cell_type) {
+ NPNR_ASSERT(net->driver.port == vcc_cell_port);
+
+ other_vcc_nets.push_back(net_pair.first);
+
+ if(need_vcc_source) {
+ IdString driver_cell = net->driver.cell->name;
+ disconnectPort(driver_cell, vcc_cell_port);
+ connectPort(vcc_net_name, driver_cell, vcc_cell_port);
+ need_vcc_source = false;
+ }
+
+ NPNR_ASSERT(net->driver.port == vcc_cell_port);
+ std::vector<PortRef> users_copy = net->users;
+ for(const PortRef & port_ref : users_copy) {
+ IdString cell = port_ref.cell->name;
+ disconnectPort(cell, port_ref.port);
+ connectPort(vcc_net_name, cell, port_ref.port);
+ }
+ }
+ }
+
+ for(IdString other_gnd_net : other_gnd_nets) {
+ NetInfo * net = getNetByAlias(other_gnd_net);
+ NPNR_ASSERT(net->users.empty());
+ }
+
+ for(IdString other_vcc_net : other_vcc_nets) {
+ NetInfo * net = getNetByAlias(other_vcc_net);
+ NPNR_ASSERT(net->users.empty());
+ }
+
+ for(IdString other_gnd_net : other_gnd_nets) {
+ NPNR_ASSERT(nets.erase(other_gnd_net));
+ gnd_net->aliases.push_back(other_gnd_net);
+ net_aliases[other_gnd_net] = gnd_net_name;
+ }
+
+ for(IdString other_vcc_net : other_vcc_nets) {
+ NPNR_ASSERT(nets.erase(other_vcc_net));
+ vcc_net->aliases.push_back(other_vcc_net);
+ net_aliases[other_vcc_net] = vcc_net_name;
+ }
+
+ if(need_gnd_source) {
+ CellInfo * gnd_cell = createCell(gnd_cell_type, gnd_cell_type);
+ gnd_cell->addOutput(gnd_cell_port);
+ connectPort(gnd_net_name, gnd_cell_type, gnd_cell_port);
+ }
+
+ if(need_vcc_source) {
+ CellInfo * vcc_cell = createCell(vcc_cell_type, vcc_cell_type);
+ vcc_cell->addOutput(vcc_cell_port);
+ connectPort(vcc_net_name, vcc_cell_type, vcc_cell_port);
+ }
+}
+
// Instance constraint templates.
template void Arch::ArchConstraints::bindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange);
template void Arch::ArchConstraints::unbindBel(Arch::ArchConstraints::TagState *, const Arch::ConstraintRange);