Working FF example now that constant merging is done.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2021-02-19 17:28:25 -08:00
parent 2fc353d559
commit 5574455d2a
6 changed files with 218 additions and 8 deletions

View File

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

View File

@ -871,7 +871,7 @@ struct Arch : ArchAPI<ArchRanges>
uint32_t getBelChecksum(BelId bel) const override { return bel.index; }
void map_cell_pins(CellInfo *cell, int32_t mapping) const;
void map_cell_pins(CellInfo *cell, int32_t mapping);
void map_port_pins(BelId bel, CellInfo *cell) const;
TileStatus &get_tile_status(int32_t tile)
@ -1716,6 +1716,8 @@ struct Arch : ArchAPI<ArchRanges>
return is_bel_synthetic(bel);
}
}
void merge_constant_nets();
};
NEXTPNR_NAMESPACE_END

View File

@ -106,6 +106,7 @@ struct ArchCellInfo
int32_t cell_mapping;
std::unordered_map<IdString, std::vector<IdString>> cell_bel_pins;
std::unordered_set<IdString> const_ports;
};
NEXTPNR_NAMESPACE_END

View File

@ -55,6 +55,15 @@ verbose: build/$(DESIGN).netlist
--package $(PACKAGE) \
--verbose
verbose2: build/$(DESIGN).netlist
$(NEXTPNR_BIN) \
--chipdb $(BBA_PATH) \
--xdc $(DESIGN).xdc \
--netlist build/$(DESIGN).netlist \
--phys build/$(DESIGN).phys \
--package $(PACKAGE) \
--debug
debug: build/$(DESIGN).netlist
gdb --args $(NEXTPNR_BIN) \
--chipdb $(BBA_PATH) \
@ -63,6 +72,15 @@ debug: build/$(DESIGN).netlist
--phys build/$(DESIGN).phys \
--package $(PACKAGE)
debug_verbose: build/$(DESIGN).netlist
gdb --args $(NEXTPNR_BIN) \
--chipdb $(BBA_PATH) \
--xdc $(DESIGN).xdc \
--netlist build/$(DESIGN).netlist \
--phys build/$(DESIGN).phys \
--package $(PACKAGE) \
--verbose
build/$(DESIGN).dcp: build/$(DESIGN).netlist build/$(DESIGN).phys $(DESIGN).xdc
RAPIDWRIGHT_PATH=$(RAPIDWRIGHT_PATH) \
$(RAPIDWRIGHT_PATH)/scripts/invoke_rapidwright.sh \

View File

@ -1,2 +1,5 @@
set_property PACKAGE_PIN N16 [get_ports i]
set_property PACKAGE_PIN N15 [get_ports o]
set_property IOSTANDARD LVCMOS33 [get_ports i]
set_property IOSTANDARD LVCMOS33 [get_ports o]

View File

@ -269,8 +269,10 @@ static void find_non_synthetic_edges(const Context * ctx, WireId root_wire,
auto downhill_iter = pip_downhill.find(wire);
if(downhill_iter == pip_downhill.end()) {
log_warning("Wire %s never entered the real fabric?\n",
ctx->nameOfWire(wire));
if(root_wire != wire) {
log_warning("Wire %s never entered the real fabric?\n",
ctx->nameOfWire(wire));
}
continue;
}
@ -365,6 +367,9 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
// Don't emit pin map for ports.
size_t pin_count = 0;
for(const auto & pin : cell.cell_bel_pins) {
if(cell.const_ports.count(pin.first)) {
continue;
}
pin_count += pin.second.size();
}
@ -372,6 +377,10 @@ void FpgaInterchange::write_physical_netlist(const Context * ctx, const std::str
auto pin_iter = pins.begin();
for(const auto & cell_to_bel_pins : cell.cell_bel_pins) {
if(cell.const_ports.count(cell_to_bel_pins.first)) {
continue;
}
std::string cell_pin = cell_to_bel_pins.first.str(ctx);
size_t cell_pin_index = strings.get_index(cell_pin);