mirror of https://github.com/YosysHQ/nextpnr.git
gatemate: use CPE bridge (#1538)
* Add bridge support * Use bridge only if CPE is unused * do not use CPE_MULT for MUX routing * Fixed and documented * delay for CPE_BRIDGE * Convert bridge pips into bels Co-authored-by: Miodrag Milanovic <mmicko@gmail.com> * recursively reassign bridges * reconnect cell ports to new nets * handle inversion bits * sort data in output for easier compare * one to be removed after testing * debug message * Remove need for notifyPipChange * use same logic for detecting bridge pips * make sure that the pip used is the one assigned * one wire may feed multiple ports * remove #if * clean up wire binding * add debugging * fix * clangformat * put back to error * use tile instead of getting name out of bel/pip * bump chipdb * adressing review comments * Addressed last one --------- Co-authored-by: Lofty <dan.ravensloft@gmail.com>
This commit is contained in:
parent
4e4f4ab113
commit
3eb682bcbb
|
|
@ -65,6 +65,11 @@ struct BitstreamBackend
|
|||
|
||||
WireId cursor = dst_wire;
|
||||
bool invert = false;
|
||||
if (net_info->driver.cell && net_info->driver.cell->type == id_CPE_BRIDGE &&
|
||||
net_info->driver.port == id_MUXOUT) {
|
||||
int val = int_or_default(net_info->driver.cell->params, id_C_SN, 0) + 1;
|
||||
invert ^= need_inversion(net_info->driver.cell, ctx->idf("IN%d", val));
|
||||
}
|
||||
while (cursor != WireId() && cursor != src_wire) {
|
||||
auto it = net_info->wires.find(cursor);
|
||||
|
||||
|
|
@ -147,8 +152,7 @@ struct BitstreamBackend
|
|||
|
||||
void export_connection(ChipConfig &cc, PipId pip)
|
||||
{
|
||||
const auto extra_data =
|
||||
*reinterpret_cast<const GateMatePipExtraDataPOD *>(chip_pip_info(ctx->chip_info, pip).extra_data.get());
|
||||
const auto &extra_data = *uarch->pip_extra_data(pip);
|
||||
if (extra_data.type == PipExtra::PIP_EXTRA_MUX && (extra_data.flags & MUX_VISIBLE)) {
|
||||
IdString name = IdString(extra_data.name);
|
||||
CfgLoc loc = get_config_loc(pip.tile);
|
||||
|
|
@ -293,7 +297,8 @@ struct BitstreamBackend
|
|||
case id_IOSEL.index:
|
||||
for (auto &p : params) {
|
||||
bank[loc.die][ctx->get_bel_package_pin(cell.second.get()->bel)->pad_bank] = 1;
|
||||
cc.tiles[loc].add_word(stringf("GPIO.%s", p.first.c_str(ctx)), p.second.as_bits());
|
||||
cc.tiles[loc].add_word(stringf("GPIO.%s", p.first.c_str(ctx)), p.second.as_bits(),
|
||||
cell.second->name.c_str(ctx));
|
||||
}
|
||||
break;
|
||||
case id_CPE_CPLINES.index:
|
||||
|
|
@ -308,6 +313,7 @@ struct BitstreamBackend
|
|||
case id_CPE_LATCH.index:
|
||||
case id_CPE_RAMI.index:
|
||||
case id_CPE_RAMO.index:
|
||||
case id_CPE_BRIDGE.index:
|
||||
case id_CPE_RAMIO.index: {
|
||||
// Update configuration bits based on signal inversion
|
||||
dict<IdString, Property> params = cell.second->params;
|
||||
|
|
@ -409,23 +415,27 @@ struct BitstreamBackend
|
|||
}
|
||||
break;
|
||||
}
|
||||
cc.tiles[loc].add_word(stringf("CPE%d.%s", id, name.c_str(ctx)), p.second.as_bits());
|
||||
cc.tiles[loc].add_word(stringf("CPE%d.%s", id, name.c_str(ctx)), p.second.as_bits(),
|
||||
cell.second->name.c_str(ctx));
|
||||
}
|
||||
} break;
|
||||
case id_CLKIN.index: {
|
||||
for (auto &p : params) {
|
||||
cc.configs[loc.die].add_word(stringf("CLKIN.%s", p.first.c_str(ctx)), p.second.as_bits());
|
||||
cc.configs[loc.die].add_word(stringf("CLKIN.%s", p.first.c_str(ctx)), p.second.as_bits(),
|
||||
cell.second->name.c_str(ctx));
|
||||
}
|
||||
} break;
|
||||
case id_GLBOUT.index: {
|
||||
for (auto &p : params) {
|
||||
cc.configs[loc.die].add_word(stringf("GLBOUT.%s", p.first.c_str(ctx)), p.second.as_bits());
|
||||
cc.configs[loc.die].add_word(stringf("GLBOUT.%s", p.first.c_str(ctx)), p.second.as_bits(),
|
||||
cell.second->name.c_str(ctx));
|
||||
}
|
||||
} break;
|
||||
case id_PLL.index: {
|
||||
Loc l = ctx->getBelLocation(cell.second->bel);
|
||||
for (auto &p : params) {
|
||||
cc.configs[loc.die].add_word(stringf("PLL%d.%s", l.z - 2, p.first.c_str(ctx)), p.second.as_bits());
|
||||
cc.configs[loc.die].add_word(stringf("PLL%d.%s", l.z - 2, p.first.c_str(ctx)), p.second.as_bits(),
|
||||
cell.second->name.c_str(ctx));
|
||||
}
|
||||
} break;
|
||||
case id_RAM.index: {
|
||||
|
|
|
|||
|
|
@ -43,12 +43,14 @@ std::ostream &operator<<(std::ostream &out, const ConfigWord &cw)
|
|||
|
||||
std::ostream &operator<<(std::ostream &out, const TileConfig &tc)
|
||||
{
|
||||
for (const auto &cword : tc.cwords)
|
||||
auto sorted = tc.cwords;
|
||||
std::sort(sorted.begin(), sorted.end(), [](const ConfigWord &a, const ConfigWord &b) { return a.name < b.name; });
|
||||
for (const auto &cword : sorted)
|
||||
out << cword;
|
||||
return out;
|
||||
}
|
||||
|
||||
void TileConfig::add_word(const std::string &name, const std::vector<bool> &value)
|
||||
void TileConfig::add_word(const std::string &name, const std::vector<bool> &value, const char *c)
|
||||
{
|
||||
if (!added.count(name)) {
|
||||
cwords.push_back({name, value});
|
||||
|
|
@ -56,7 +58,7 @@ void TileConfig::add_word(const std::string &name, const std::vector<bool> &valu
|
|||
} else {
|
||||
auto val = added.at(name);
|
||||
if (val != value)
|
||||
log_error("Trying to add value to already assigned word %s\n", name.c_str());
|
||||
log_error("Trying to add value to already assigned word %s for %s\n", name.c_str(), c ? c : "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ struct TileConfig
|
|||
std::vector<ConfigWord> cwords;
|
||||
std::map<std::string, std::vector<bool>> added;
|
||||
|
||||
void add_word(const std::string &name, const std::vector<bool> &value);
|
||||
void add_word(const std::string &name, const std::vector<bool> &value, const char *c = nullptr);
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdStrin
|
|||
return false;
|
||||
} else if (cell->type.in(id_CPE_CPLINES)) {
|
||||
return true;
|
||||
} else if (cell->type.in(id_CPE_BRIDGE)) {
|
||||
return true;
|
||||
} else if (cell->type.in(id_CPE_COMP)) {
|
||||
return get_delay_from_tmg_db(fromPort == id_COMB1 ? id_timing_comb1_compout : id_timing_comb2_compout, delay);
|
||||
} else if (cell->type.in(id_CPE_RAMI, id_CPE_RAMO, id_CPE_RAMIO)) {
|
||||
|
|
@ -192,6 +194,10 @@ TimingPortClass GateMateImpl::getPortTimingClass(const CellInfo *cell, IdString
|
|||
if (port.in(id_OUT1, id_OUT2, id_COMPOUT, id_CINX, id_PINX, id_CINY1, id_PINY1, id_CINY2, id_PINY2))
|
||||
return TMG_COMB_INPUT;
|
||||
return TMG_COMB_OUTPUT;
|
||||
} else if (cell->type.in(id_CPE_BRIDGE)) {
|
||||
if (port.in(id_MUXOUT))
|
||||
return TMG_COMB_OUTPUT;
|
||||
return TMG_COMB_INPUT;
|
||||
} else if (cell->type.in(id_CPE_FF, id_CPE_FF_L, id_CPE_FF_U, id_CPE_LATCH)) {
|
||||
if (port == id_CLK)
|
||||
return TMG_CLOCK_INPUT;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ enum MuxFlags
|
|||
MUX_INVERT = 1,
|
||||
MUX_VISIBLE = 2,
|
||||
MUX_CONFIG = 4,
|
||||
MUX_ROUTING = 8,
|
||||
};
|
||||
|
||||
enum PipExtra
|
||||
|
|
@ -103,7 +104,7 @@ enum CPE_Z
|
|||
CPE_COMP_Z = 6,
|
||||
CPE_CPLINES_Z = 7,
|
||||
CPE_LT_FULL_Z = 8,
|
||||
|
||||
CPE_BRIDGE_Z = 9,
|
||||
RAM_FULL_Z = 10,
|
||||
RAM_HALF_U_Z = 11,
|
||||
RAM_HALF_L_Z = 12,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "gatemate.h"
|
||||
#include "log.h"
|
||||
#include "placer_heap.h"
|
||||
|
|
@ -278,6 +280,26 @@ void GateMateImpl::postPlace()
|
|||
{
|
||||
repack();
|
||||
ctx->assignArchInfo();
|
||||
used_cpes.resize(ctx->getGridDimX() * ctx->getGridDimY());
|
||||
for (auto &cell : ctx->cells) {
|
||||
// We need to skip CPE_MULT since using CP outputs is mandatory
|
||||
// even if output is actually not connected
|
||||
bool marked_used = cell.second.get()->type == id_CPE_MULT;
|
||||
// Can not use FF for OUT2 if CPE is used in bridge mode
|
||||
if (cell.second.get()->type == id_CPE_FF && ctx->getBelLocation(cell.second.get()->bel).z == CPE_FF_U_Z)
|
||||
marked_used = true;
|
||||
if (marked_used)
|
||||
used_cpes[cell.second.get()->bel.tile] = true;
|
||||
}
|
||||
}
|
||||
bool GateMateImpl::checkPipAvail(PipId pip) const
|
||||
{
|
||||
const auto &extra_data = *pip_extra_data(pip);
|
||||
if (extra_data.type != PipExtra::PIP_EXTRA_MUX || (extra_data.flags & MUX_ROUTING) == 0)
|
||||
return true;
|
||||
if (used_cpes[pip.tile])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GateMateImpl::preRoute()
|
||||
|
|
@ -287,8 +309,120 @@ void GateMateImpl::preRoute()
|
|||
ctx->assignArchInfo();
|
||||
}
|
||||
|
||||
void GateMateImpl::reassign_bridges(NetInfo *ni, const dict<WireId, PipMap> &net_wires, WireId wire,
|
||||
dict<WireId, IdString> &wire_to_net, int &num)
|
||||
{
|
||||
wire_to_net.insert({wire, ni->name});
|
||||
|
||||
for (auto pip : ctx->getPipsDownhill(wire)) {
|
||||
auto dst = ctx->getPipDstWire(pip);
|
||||
|
||||
// Ignore wires not part of the net
|
||||
auto it = net_wires.find(dst);
|
||||
if (it == net_wires.end())
|
||||
continue;
|
||||
// Ignore pips if the wire is driven by another pip.
|
||||
if (pip != it->second.pip)
|
||||
continue;
|
||||
// Ignore wires already visited.
|
||||
if (wire_to_net.count(dst))
|
||||
continue;
|
||||
|
||||
const auto &extra_data = *pip_extra_data(pip);
|
||||
// If not a bridge, just recurse.
|
||||
if (extra_data.type != PipExtra::PIP_EXTRA_MUX || !(extra_data.flags & MUX_ROUTING)) {
|
||||
reassign_bridges(ni, net_wires, dst, wire_to_net, num);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have a bridge that needs to be translated to a bel.
|
||||
IdString name = ctx->idf("%s$bridge%d", ni->name.c_str(ctx), num);
|
||||
|
||||
IdStringList id = ctx->getPipName(pip);
|
||||
Loc loc = ctx->getPipLocation(pip);
|
||||
BelId bel = ctx->getBelByLocation({loc.x, loc.y, CPE_BRIDGE_Z});
|
||||
CellInfo *cell = ctx->createCell(name, id_CPE_BRIDGE);
|
||||
ctx->bindBel(bel, cell, PlaceStrength::STRENGTH_FIXED);
|
||||
cell->params[id_C_BR] = Property(Property::State::S1, 1);
|
||||
cell->params[id_C_SN] = Property(extra_data.value, 3);
|
||||
|
||||
NetInfo *new_net = ctx->createNet(ctx->idf("%s$muxout", name.c_str(ctx)));
|
||||
IdString in_port = ctx->idf("IN%d", extra_data.value + 1);
|
||||
|
||||
cell->addInput(in_port);
|
||||
cell->connectPort(in_port, ni);
|
||||
|
||||
cell->addOutput(id_MUXOUT);
|
||||
cell->connectPort(id_MUXOUT, new_net);
|
||||
|
||||
num++;
|
||||
|
||||
reassign_bridges(new_net, net_wires, dst, wire_to_net, num);
|
||||
}
|
||||
}
|
||||
|
||||
void GateMateImpl::postRoute()
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
pool<IdString> nets_with_bridges;
|
||||
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
for (auto &w : ni->wires) {
|
||||
if (w.second.pip != PipId()) {
|
||||
const auto &extra_data = *pip_extra_data(w.second.pip);
|
||||
if (extra_data.type == PipExtra::PIP_EXTRA_MUX && (extra_data.flags & MUX_ROUTING)) {
|
||||
this->cpe_bridges.insert({w.second.pip, ni->name});
|
||||
nets_with_bridges.insert(ni->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto net_name : nets_with_bridges) {
|
||||
auto *ni = ctx->nets.at(net_name).get();
|
||||
auto net_wires = ni->wires; // copy wires to preserve across unbind/rebind.
|
||||
auto wire_to_net = dict<WireId, IdString>{};
|
||||
auto wire_to_port = dict<WireId, std::vector<PortRef>>{};
|
||||
|
||||
for (auto &usr : ni->users)
|
||||
for (auto sink_wire : ctx->getNetinfoSinkWires(ni, usr)) {
|
||||
auto result = wire_to_port.find(sink_wire);
|
||||
if (result == wire_to_port.end())
|
||||
wire_to_port.insert({sink_wire, std::vector<PortRef>{usr}});
|
||||
else
|
||||
result->second.push_back(usr);
|
||||
}
|
||||
|
||||
// traverse the routing tree to assign bridge nets to wires.
|
||||
reassign_bridges(ni, net_wires, ctx->getNetinfoSourceWire(ni), wire_to_net, num);
|
||||
|
||||
for (auto &pair : net_wires)
|
||||
ctx->unbindWire(pair.first);
|
||||
|
||||
for (auto &pair : net_wires) {
|
||||
auto wire = pair.first;
|
||||
auto pip = pair.second.pip;
|
||||
auto strength = pair.second.strength;
|
||||
auto *net = ctx->nets.at(wire_to_net.at(wire)).get();
|
||||
if (pip == PipId())
|
||||
ctx->bindWire(wire, net, strength);
|
||||
else
|
||||
ctx->bindPip(pip, net, strength);
|
||||
|
||||
if (wire_to_port.count(wire)) {
|
||||
for (auto sink : wire_to_port.at(wire)) {
|
||||
NPNR_ASSERT(sink.cell != nullptr && sink.port != IdString());
|
||||
sink.cell->disconnectPort(sink.port);
|
||||
sink.cell->connectPort(sink.port, net);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->assignArchInfo();
|
||||
|
||||
const ArchArgs &args = ctx->args;
|
||||
if (args.options.count("out")) {
|
||||
write_bitstream(args.device, args.options.at("out"));
|
||||
|
|
@ -430,8 +564,7 @@ bool GateMateImpl::isValidBelForCellType(IdString cell_type, BelId bel) const
|
|||
|
||||
bool GateMateImpl::isPipInverting(PipId pip) const
|
||||
{
|
||||
const auto &extra_data =
|
||||
*reinterpret_cast<const GateMatePipExtraDataPOD *>(chip_pip_info(ctx->chip_info, pip).extra_data.get());
|
||||
const auto &extra_data = *pip_extra_data(pip);
|
||||
return extra_data.type == PipExtra::PIP_EXTRA_MUX && (extra_data.flags & MUX_INVERT);
|
||||
}
|
||||
|
||||
|
|
@ -440,6 +573,11 @@ const GateMateBelExtraDataPOD *GateMateImpl::bel_extra_data(BelId bel) const
|
|||
return reinterpret_cast<const GateMateBelExtraDataPOD *>(chip_bel_info(ctx->chip_info, bel).extra_data.get());
|
||||
}
|
||||
|
||||
const GateMatePipExtraDataPOD *GateMateImpl::pip_extra_data(PipId pip) const
|
||||
{
|
||||
return reinterpret_cast<const GateMatePipExtraDataPOD *>(chip_pip_info(ctx->chip_info, pip).extra_data.get());
|
||||
}
|
||||
|
||||
struct GateMateArch : HimbaechelArch
|
||||
{
|
||||
GateMateArch() : HimbaechelArch("gatemate") {};
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ struct GateMateImpl : HimbaechelAPI
|
|||
|
||||
BoundingBox getRouteBoundingBox(WireId src, WireId dst) const override;
|
||||
void expandBoundingBox(BoundingBox &bb) const override;
|
||||
bool checkPipAvail(PipId pip) const override;
|
||||
bool checkPipAvailForNet(PipId pip, const NetInfo *net) const override { return checkPipAvail(pip); };
|
||||
|
||||
bool isBelLocationValid(BelId bel, bool explain_invalid = false) const override;
|
||||
delay_t estimateDelay(WireId src, WireId dst) const override;
|
||||
|
|
@ -69,6 +71,7 @@ struct GateMateImpl : HimbaechelAPI
|
|||
bool isPipInverting(PipId pip) const override;
|
||||
|
||||
const GateMateTileExtraDataPOD *tile_extra_data(int tile) const;
|
||||
const GateMatePipExtraDataPOD *pip_extra_data(PipId pip) const;
|
||||
|
||||
int get_dff_config(CellInfo *dff) const;
|
||||
int get_ram_config(CellInfo *ram) const;
|
||||
|
|
@ -83,6 +86,8 @@ struct GateMateImpl : HimbaechelAPI
|
|||
pool<IdString> multiplier_a_passthru_uppers;
|
||||
pool<IdString> multiplier_zero_drivers;
|
||||
std::vector<CellInfo *> multipliers;
|
||||
std::vector<bool> used_cpes;
|
||||
dict<PipId, IdString> cpe_bridges;
|
||||
int fpga_mode;
|
||||
int timing_mode;
|
||||
|
||||
|
|
@ -97,6 +102,8 @@ struct GateMateImpl : HimbaechelAPI
|
|||
void assign_cell_info();
|
||||
void route_clock();
|
||||
void route_mult();
|
||||
void reassign_bridges(NetInfo *net, const dict<WireId, PipMap> &net_wires, WireId wire,
|
||||
dict<WireId, IdString> &wire_to_net, int &num);
|
||||
void repack();
|
||||
|
||||
const GateMateBelExtraDataPOD *bel_extra_data(BelId bel) const;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ PIP_EXTRA_MUX = 1
|
|||
MUX_INVERT = 1
|
||||
MUX_VISIBLE = 2
|
||||
MUX_CONFIG = 4
|
||||
MUX_ROUTING = 8
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--lib", help="Project Peppercorn python database script path", type=str, required=True)
|
||||
|
|
@ -193,7 +194,7 @@ def set_timings(ch):
|
|||
# assert k in timing, f"pip class {k} not found in timing data"
|
||||
# tmg.set_pip_class(grade=speed, name=k, delay=convert_timing(timing[k]))
|
||||
|
||||
EXPECTED_VERSION = 1.5
|
||||
EXPECTED_VERSION = 1.6
|
||||
|
||||
def main():
|
||||
# Range needs to be +1, but we are adding +2 more to coordinates, since
|
||||
|
|
@ -233,7 +234,7 @@ def main():
|
|||
tt.create_wire(wire.name, wire.type)
|
||||
for prim in sorted(die.get_primitives_for_type(type_name)):
|
||||
bel = tt.create_bel(prim.name, prim.type, prim.z)
|
||||
if (prim.name in ["CPE_LT_FULL", "RAM"]):
|
||||
if (prim.name in ["CPE_LT_FULL", "CPE_BRIDGE", "RAM"]):
|
||||
bel.flags |= BEL_FLAG_HIDDEN
|
||||
extra = BelExtraData()
|
||||
for constr in sorted(die.get_pins_constraint(type_name, prim.name, prim.type)):
|
||||
|
|
@ -256,6 +257,8 @@ def main():
|
|||
plane = int(mux.name[8:10])
|
||||
if mux.name.startswith("SB_DRIVE"):
|
||||
plane = int(mux.name[10:12])
|
||||
if mux.name == "CPE.C_SN":
|
||||
mux_flags |= MUX_ROUTING
|
||||
pp.extra_data = PipExtraData(PIP_EXTRA_MUX, ch.strs.id(mux.name), mux.bits, mux.value, mux_flags, plane)
|
||||
|
||||
# Setup tile grid
|
||||
|
|
|
|||
|
|
@ -272,8 +272,7 @@ void GateMatePacker::insert_bufg(CellInfo *cell, IdString port)
|
|||
CellInfo *bufg =
|
||||
create_cell_ptr(id_CC_BUFG, ctx->idf("%s$BUFG_%s", cell->name.c_str(ctx), port.c_str(ctx)));
|
||||
cell->movePortTo(port, bufg, id_O);
|
||||
cell->ports[port].name = port;
|
||||
cell->ports[port].type = PORT_OUT;
|
||||
cell->addOutput(port);
|
||||
NetInfo *net = ctx->createNet(ctx->idf("%s", bufg->name.c_str(ctx)));
|
||||
cell->connectPort(port, net);
|
||||
bufg->connectPort(id_I, net);
|
||||
|
|
|
|||
|
|
@ -207,8 +207,7 @@ void GateMatePacker::pack_cpe()
|
|||
ci.renamePort(id_D1, id_IN1);
|
||||
NetInfo *sel = ci.getPort(id_S0);
|
||||
ci.renamePort(id_S0, id_IN2);
|
||||
ci.ports[id_IN3].name = id_IN3;
|
||||
ci.ports[id_IN3].type = PORT_IN;
|
||||
ci.addInput(id_IN3);
|
||||
ci.connectPort(id_IN3, sel);
|
||||
ci.renamePort(id_D0, id_IN4);
|
||||
ci.disconnectPort(id_D1);
|
||||
|
|
@ -262,8 +261,7 @@ void GateMatePacker::pack_cpe()
|
|||
// Reconnect net
|
||||
NetInfo *ci_out_conn = ctx->createNet(ctx->idf("%s$out", ci.name.c_str(ctx)));
|
||||
ci.connectPort(id_OUT, ci_out_conn);
|
||||
lower->ports[id_COMBIN].name = id_COMBIN;
|
||||
lower->ports[id_COMBIN].type = PORT_IN;
|
||||
lower->addInput(id_COMBIN);
|
||||
lower->connectPort(id_COMBIN, ci_out_conn);
|
||||
dff->disconnectPort(id_DIN);
|
||||
dff->connectPort(id_DIN, ci_out_conn);
|
||||
|
|
@ -291,8 +289,7 @@ void GateMatePacker::pack_cpe()
|
|||
|
||||
NetInfo *ci_out_conn = ctx->createNet(ctx->idf("%s$combin", ci->name.c_str(ctx)));
|
||||
upper->connectPort(id_OUT, ci_out_conn);
|
||||
ci->ports[id_COMBIN].name = id_COMBIN;
|
||||
ci->ports[id_COMBIN].type = PORT_IN;
|
||||
ci->addInput(id_COMBIN);
|
||||
ci->connectPort(id_COMBIN, ci_out_conn);
|
||||
}
|
||||
l2t5_list.clear();
|
||||
|
|
@ -388,8 +385,7 @@ void GateMatePacker::pack_cpe()
|
|||
ci.type = (ci.type == id_CC_DLT) ? id_CPE_LATCH : id_CPE_FF;
|
||||
NetInfo *conn = ctx->createNet(ctx->idf("%s$di", ci.name.c_str(ctx)));
|
||||
lt->connectPort(id_OUT, conn);
|
||||
ci.ports[id_DIN].name = id_DIN;
|
||||
ci.ports[id_DIN].type = PORT_IN;
|
||||
ci.addInput(id_DIN);
|
||||
ci.connectPort(id_DIN, conn);
|
||||
}
|
||||
dff_list.clear();
|
||||
|
|
@ -577,8 +573,7 @@ void GateMatePacker::pack_addf()
|
|||
NetInfo *ci_conn = ctx->createNet(ctx->idf("%s$ci_net", root->name.c_str(ctx)));
|
||||
ci_cplines->connectPort(id_COUTY1, ci_conn);
|
||||
|
||||
root->ports[id_CINY1].name = id_CINY1;
|
||||
root->ports[id_CINY1].type = PORT_IN;
|
||||
root->addInput(id_CINY1);
|
||||
root->connectPort(id_CINY1, ci_conn);
|
||||
|
||||
for (size_t i = 0; i < grp.size(); i++) {
|
||||
|
|
@ -646,8 +641,7 @@ void GateMatePacker::pack_addf()
|
|||
NetInfo *co_conn = ctx->createNet(ctx->idf("%s$co_net", cy->name.c_str(ctx)));
|
||||
|
||||
co_lower->connectPort(id_CINY1, co_conn);
|
||||
cy->ports[id_COUTY1].name = id_COUTY1;
|
||||
cy->ports[id_COUTY1].type = PORT_OUT;
|
||||
cy->addOutput(id_COUTY1);
|
||||
cy->connectPort(id_COUTY1, co_conn);
|
||||
|
||||
cy->movePortTo(id_CO, co_lower, id_OUT);
|
||||
|
|
@ -660,8 +654,7 @@ void GateMatePacker::pack_addf()
|
|||
if (usr.cell->type == id_CC_ADDF || usr.port == id_CI) {
|
||||
usr.cell->disconnectPort(id_CI);
|
||||
NetInfo *co_conn = ctx->createNet(ctx->idf("%s$co_net", cy->name.c_str(ctx)));
|
||||
cy->ports[id_COUTY1].name = id_COUTY1;
|
||||
cy->ports[id_COUTY1].type = PORT_OUT;
|
||||
cy->addOutput(id_COUTY1);
|
||||
cy->connectPort(id_COUTY1, co_conn);
|
||||
usr.cell->connectPort(id_CI, co_conn);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -518,8 +518,7 @@ void GateMatePacker::pack_io_sel()
|
|||
if (cpe_half) {
|
||||
if (cpe_half->getPort(id_IN1) != oddr->getPort(id_DDR))
|
||||
log_error("DDR port use signal different than already occupied DDR source.\n");
|
||||
ci.ports[id_DDR].name = id_DDR;
|
||||
ci.ports[id_DDR].type = PORT_IN;
|
||||
ci.addInput(id_DDR);
|
||||
ci.connectPort(id_DDR, cpe_ramio->getPort(id_RAM_O));
|
||||
} else {
|
||||
auto l = reinterpret_cast<const GateMatePadExtraDataPOD *>(pad->extra_data.get());
|
||||
|
|
|
|||
|
|
@ -430,8 +430,7 @@ void GateMatePacker::pack_mult()
|
|||
|
||||
NetInfo *comb2_conn = ctx->createNet(ctx->idf("%s$carrycomb2", name.c_str(ctx)));
|
||||
carry_upper->connectPort(id_OUT, comb2_conn);
|
||||
carry_lower->ports[id_COMBIN].name = id_COMBIN;
|
||||
carry_lower->ports[id_COMBIN].type = PORT_IN;
|
||||
carry_lower->addInput(id_COMBIN);
|
||||
carry_lower->connectPort(id_COMBIN, comb2_conn);
|
||||
|
||||
NetInfo *comp_in = ctx->createNet(ctx->idf("%s$carry$comp_in", name.c_str(ctx)));
|
||||
|
|
@ -461,8 +460,7 @@ void GateMatePacker::pack_mult()
|
|||
|
||||
NetInfo *comb2_conn = ctx->createNet(ctx->idf("%s$multf%c$comb2", name.c_str(ctx), is_even_x ? 'a' : 'b'));
|
||||
multfab_upper->connectPort(id_OUT, comb2_conn);
|
||||
multfab_lower->ports[id_COMBIN].name = id_COMBIN;
|
||||
multfab_lower->ports[id_COMBIN].type = PORT_IN;
|
||||
multfab_lower->addInput(id_COMBIN);
|
||||
multfab_lower->connectPort(id_COMBIN, comb2_conn);
|
||||
multfab_comp->connectPort(id_COMB2, comb2_conn);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,7 @@ void GateMateImpl::route_clock()
|
|||
};
|
||||
|
||||
auto pip_plane = [&](PipId pip) {
|
||||
const auto &extra_data =
|
||||
*reinterpret_cast<const GateMatePipExtraDataPOD *>(chip_pip_info(ctx->chip_info, pip).extra_data.get());
|
||||
const auto &extra_data = *pip_extra_data(pip);
|
||||
if (extra_data.type != PipExtra::PIP_EXTRA_MUX)
|
||||
return uint8_t{0};
|
||||
return extra_data.plane;
|
||||
|
|
|
|||
Loading…
Reference in New Issue