Refactor chain finder to its own file
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
6afc2c75fd
commit
a27c7b45de
68
common/chain_utils.h
Normal file
68
common/chain_utils.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* nextpnr -- Next Generation Place and Route
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018 David Shah <david@symbioticeda.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CHAIN_UTILS_H
|
||||||
|
#define CHAIN_UTILS_H
|
||||||
|
|
||||||
|
#include "nextpnr.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
struct CellChain
|
||||||
|
{
|
||||||
|
std::vector<CellInfo *> cells;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generic chain finder
|
||||||
|
template <typename F1, typename F2, typename F3>
|
||||||
|
std::vector<CellChain> find_chains(const Context *ctx, F1 cell_type_predicate, F2 get_previous, F3 get_next,
|
||||||
|
size_t min_length = 2)
|
||||||
|
{
|
||||||
|
std::set<IdString> chained;
|
||||||
|
std::vector<CellChain> chains;
|
||||||
|
for (auto cell : sorted(ctx->cells)) {
|
||||||
|
if (chained.find(cell.first) != chained.end())
|
||||||
|
continue;
|
||||||
|
CellInfo *ci = cell.second;
|
||||||
|
if (cell_type_predicate(ctx, ci)) {
|
||||||
|
CellInfo *start = ci;
|
||||||
|
CellInfo *prev_start = ci;
|
||||||
|
while (prev_start != nullptr) {
|
||||||
|
start = prev_start;
|
||||||
|
prev_start = get_previous(ctx, start);
|
||||||
|
}
|
||||||
|
CellChain chain;
|
||||||
|
CellInfo *end = start;
|
||||||
|
while (end != nullptr) {
|
||||||
|
chain.cells.push_back(end);
|
||||||
|
end = get_next(ctx, end);
|
||||||
|
}
|
||||||
|
if (chain.cells.size() >= min_length) {
|
||||||
|
chains.push_back(chain);
|
||||||
|
for (auto c : chain.cells)
|
||||||
|
chained.insert(c->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chains;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
||||||
|
#endif
|
@ -74,7 +74,8 @@ void print_utilisation(const Context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect a net to a port
|
// Connect a net to a port
|
||||||
void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name) {
|
void connect_port(const Context *ctx, NetInfo *net, CellInfo *cell, IdString port_name)
|
||||||
|
{
|
||||||
PortInfo &port = cell->ports.at(port_name);
|
PortInfo &port = cell->ports.at(port_name);
|
||||||
NPNR_ASSERT(port.net == nullptr);
|
NPNR_ASSERT(port.net == nullptr);
|
||||||
port.net = net;
|
port.net = net;
|
||||||
|
40
ecp5/pack.cc
40
ecp5/pack.cc
@ -18,13 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "cells.h"
|
#include "cells.h"
|
||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <boost/optional.hpp>
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
static bool is_nextpnr_iob(Context *ctx, CellInfo *cell)
|
static bool is_nextpnr_iob(Context *ctx, CellInfo *cell)
|
||||||
@ -313,9 +313,9 @@ class Ecp5Packer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a feed in to the carry chain
|
// Create a feed in to the carry chain
|
||||||
CellInfo *make_carry_feed_in(NetInfo *carry, PortRef chain_in) {
|
CellInfo *make_carry_feed_in(NetInfo *carry, PortRef chain_in)
|
||||||
std::unique_ptr<CellInfo> feedin =
|
{
|
||||||
create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"));
|
std::unique_ptr<CellInfo> feedin = create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"));
|
||||||
|
|
||||||
feedin->params[ctx->id("MODE")] = "CCU2";
|
feedin->params[ctx->id("MODE")] = "CCU2";
|
||||||
feedin->params[ctx->id("LUT0_INITVAL")] = "10"; // LUT4 = 0; LUT2 = A
|
feedin->params[ctx->id("LUT0_INITVAL")] = "10"; // LUT4 = 0; LUT2 = A
|
||||||
@ -323,9 +323,11 @@ class Ecp5Packer
|
|||||||
feedin->params[ctx->id("INJECT1_0")] = "NO";
|
feedin->params[ctx->id("INJECT1_0")] = "NO";
|
||||||
feedin->params[ctx->id("INJECT1_1")] = "YES";
|
feedin->params[ctx->id("INJECT1_1")] = "YES";
|
||||||
|
|
||||||
carry->users.erase(std::remove_if(carry->users.begin(), carry->users.end(), [chain_in](const PortRef &user) {
|
carry->users.erase(std::remove_if(carry->users.begin(), carry->users.end(),
|
||||||
return user.port == chain_in.port && user.cell == chain_in.cell;
|
[chain_in](const PortRef &user) {
|
||||||
}), carry->users.end());
|
return user.port == chain_in.port && user.cell == chain_in.cell;
|
||||||
|
}),
|
||||||
|
carry->users.end());
|
||||||
connect_port(ctx, carry, feedin.get(), id_A0);
|
connect_port(ctx, carry, feedin.get(), id_A0);
|
||||||
|
|
||||||
std::unique_ptr<NetInfo> new_carry(new NetInfo());
|
std::unique_ptr<NetInfo> new_carry(new NetInfo());
|
||||||
@ -341,9 +343,9 @@ class Ecp5Packer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a feed out and loop through from the carry chain
|
// Create a feed out and loop through from the carry chain
|
||||||
CellInfo *make_carry_feed_out(NetInfo *carry, boost::optional<PortRef> chain_next) {
|
CellInfo *make_carry_feed_out(NetInfo *carry, boost::optional<PortRef> chain_next)
|
||||||
std::unique_ptr<CellInfo> feedout =
|
{
|
||||||
create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"));
|
std::unique_ptr<CellInfo> feedout = create_ecp5_cell(ctx, ctx->id("TRELLIS_SLICE"));
|
||||||
feedout->params[ctx->id("MODE")] = "CCU2";
|
feedout->params[ctx->id("MODE")] = "CCU2";
|
||||||
feedout->params[ctx->id("LUT0_INITVAL")] = "0";
|
feedout->params[ctx->id("LUT0_INITVAL")] = "0";
|
||||||
feedout->params[ctx->id("LUT1_INITVAL")] = "10"; // LUT4 = 0; LUT2 = A
|
feedout->params[ctx->id("LUT1_INITVAL")] = "10"; // LUT4 = 0; LUT2 = A
|
||||||
@ -364,9 +366,11 @@ class Ecp5Packer
|
|||||||
// Loop back into LUT4_1 for feedthrough
|
// Loop back into LUT4_1 for feedthrough
|
||||||
connect_port(ctx, carry, feedout.get(), id_A1);
|
connect_port(ctx, carry, feedout.get(), id_A1);
|
||||||
|
|
||||||
carry->users.erase(std::remove_if(carry->users.begin(), carry->users.end(), [chain_next](const PortRef &user) {
|
carry->users.erase(std::remove_if(carry->users.begin(), carry->users.end(),
|
||||||
return user.port == chain_next->port && user.cell == chain_next->cell;
|
[chain_next](const PortRef &user) {
|
||||||
}), carry->users.end());
|
return user.port == chain_next->port && user.cell == chain_next->cell;
|
||||||
|
}),
|
||||||
|
carry->users.end());
|
||||||
|
|
||||||
std::unique_ptr<NetInfo> new_cout(new NetInfo());
|
std::unique_ptr<NetInfo> new_cout(new NetInfo());
|
||||||
new_cout->name = ctx->id(feedout->name.str(ctx) + "$FCO");
|
new_cout->name = ctx->id(feedout->name.str(ctx) + "$FCO");
|
||||||
@ -376,8 +380,7 @@ class Ecp5Packer
|
|||||||
|
|
||||||
IdString new_cout_name = new_cout->name;
|
IdString new_cout_name = new_cout->name;
|
||||||
ctx->nets[new_cout_name] = std::move(new_cout);
|
ctx->nets[new_cout_name] = std::move(new_cout);
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CellInfo *feedout_ptr = feedout.get();
|
CellInfo *feedout_ptr = feedout.get();
|
||||||
new_cells.push_back(std::move(feedout));
|
new_cells.push_back(std::move(feedout));
|
||||||
@ -386,15 +389,10 @@ class Ecp5Packer
|
|||||||
ctx->nets[new_cin_name] = std::move(new_cin);
|
ctx->nets[new_cin_name] = std::move(new_cin);
|
||||||
|
|
||||||
return feedout_ptr;
|
return feedout_ptr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack carries and set up appropriate relative constraints
|
// Pack carries and set up appropriate relative constraints
|
||||||
void pack_carries()
|
void pack_carries() { log_info("Packing carries...\n"); }
|
||||||
{
|
|
||||||
log_info("Packing carries...\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pack LUTs that have been paired together
|
// Pack LUTs that have been paired together
|
||||||
void pack_lut_pairs()
|
void pack_lut_pairs()
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "cells.h"
|
#include "cells.h"
|
||||||
|
#include "chain_utils.h"
|
||||||
#include "design_utils.h"
|
#include "design_utils.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "place_common.h"
|
#include "place_common.h"
|
||||||
@ -28,45 +29,6 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
struct CellChain
|
|
||||||
{
|
|
||||||
std::vector<CellInfo *> cells;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generic chain finder
|
|
||||||
template <typename F1, typename F2, typename F3>
|
|
||||||
std::vector<CellChain> find_chains(const Context *ctx, F1 cell_type_predicate, F2 get_previous, F3 get_next,
|
|
||||||
size_t min_length = 2)
|
|
||||||
{
|
|
||||||
std::set<IdString> chained;
|
|
||||||
std::vector<CellChain> chains;
|
|
||||||
for (auto cell : sorted(ctx->cells)) {
|
|
||||||
if (chained.find(cell.first) != chained.end())
|
|
||||||
continue;
|
|
||||||
CellInfo *ci = cell.second;
|
|
||||||
if (cell_type_predicate(ctx, ci)) {
|
|
||||||
CellInfo *start = ci;
|
|
||||||
CellInfo *prev_start = ci;
|
|
||||||
while (prev_start != nullptr) {
|
|
||||||
start = prev_start;
|
|
||||||
prev_start = get_previous(ctx, start);
|
|
||||||
}
|
|
||||||
CellChain chain;
|
|
||||||
CellInfo *end = start;
|
|
||||||
while (end != nullptr) {
|
|
||||||
chain.cells.push_back(end);
|
|
||||||
end = get_next(ctx, end);
|
|
||||||
}
|
|
||||||
if (chain.cells.size() >= min_length) {
|
|
||||||
chains.push_back(chain);
|
|
||||||
for (auto c : chain.cells)
|
|
||||||
chained.insert(c->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chains;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChainConstrainer
|
class ChainConstrainer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user