mirror of https://github.com/YosysHQ/nextpnr.git
Gowin. Fill in delay values in HCLK.
Fill in the delays for PIP classes related to HCLK and IODELAY. Also: - if clock routing fails, we try to use the next fastest mechanism - segment networks; - fixing harmless typos. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
764b5402e8
commit
b1c147083d
|
|
@ -62,11 +62,11 @@ struct GowinGlobalRouter
|
||||||
src = ctx->getPipSrcWire(pip);
|
src = ctx->getPipSrcWire(pip);
|
||||||
dst = ctx->getPipDstWire(pip);
|
dst = ctx->getPipDstWire(pip);
|
||||||
IdString dst_name = ctx->getWireName(dst)[1];
|
IdString dst_name = ctx->getWireName(dst)[1];
|
||||||
bool not_dsc_pip = dst_name != id_CLKOUT;
|
bool not_dcs_pip = dst_name != id_CLKOUT;
|
||||||
IdString src_type = ctx->getWireType(src);
|
IdString src_type = ctx->getWireType(src);
|
||||||
IdString dst_type = ctx->getWireType(dst);
|
IdString dst_type = ctx->getWireType(dst);
|
||||||
bool src_valid = not_dsc_pip && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK, id_DLLDLY);
|
bool src_valid = not_dcs_pip && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK, id_DLLDLY);
|
||||||
bool dst_valid = not_dsc_pip && dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I, id_HCLK);
|
bool dst_valid = not_dcs_pip && dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I, id_HCLK);
|
||||||
|
|
||||||
bool res;
|
bool res;
|
||||||
if (src == src_wire && (!src_type.in(id_IO_O, id_HCLK, id_DLLDLY_O))) {
|
if (src == src_wire && (!src_type.in(id_IO_O, id_HCLK, id_DLLDLY_O))) {
|
||||||
|
|
@ -101,11 +101,11 @@ struct GowinGlobalRouter
|
||||||
dst = ctx->getPipDstWire(pip);
|
dst = ctx->getPipDstWire(pip);
|
||||||
IdString src_name = ctx->getWireName(dst)[1];
|
IdString src_name = ctx->getWireName(dst)[1];
|
||||||
IdString dst_name = ctx->getWireName(dst)[1];
|
IdString dst_name = ctx->getWireName(dst)[1];
|
||||||
bool not_dsc_pip = dst_name != id_CLKOUT && !is_dcs_input(src_name);
|
bool not_dcs_pip = dst_name != id_CLKOUT && !is_dcs_input(src_name);
|
||||||
IdString src_type = ctx->getWireType(src);
|
IdString src_type = ctx->getWireType(src);
|
||||||
IdString dst_type = ctx->getWireType(dst);
|
IdString dst_type = ctx->getWireType(dst);
|
||||||
bool src_valid = not_dsc_pip && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK);
|
bool src_valid = not_dcs_pip && src_type.in(id_GLOBAL_CLK, id_IO_O, id_PLL_O, id_HCLK);
|
||||||
bool dst_valid = not_dsc_pip && dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I, id_HCLK);
|
bool dst_valid = not_dcs_pip && dst_type.in(id_GLOBAL_CLK, id_TILE_CLK, id_PLL_I, id_IO_I, id_HCLK);
|
||||||
|
|
||||||
// If DQCE is used, then the source can only connect to SPINEs as only they can be switched off/on.
|
// If DQCE is used, then the source can only connect to SPINEs as only they can be switched off/on.
|
||||||
bool res;
|
bool res;
|
||||||
|
|
@ -692,7 +692,7 @@ struct GowinGlobalRouter
|
||||||
log_info(" '%s' net was routed.\n", ctx->nameOf(net));
|
log_info(" '%s' net was routed.\n", ctx->nameOf(net));
|
||||||
}
|
}
|
||||||
|
|
||||||
void route_clk_net(NetInfo *net)
|
RouteResult route_clk_net(NetInfo *net)
|
||||||
{
|
{
|
||||||
RouteResult route_result = route_direct_net(net, [&](PipId pip, WireId src_wire) {
|
RouteResult route_result = route_direct_net(net, [&](PipId pip, WireId src_wire) {
|
||||||
return global_pip_filter(pip, src_wire) && segment_wire_filter(pip) && dcs_input_filter(pip);
|
return global_pip_filter(pip, src_wire) && segment_wire_filter(pip) && dcs_input_filter(pip);
|
||||||
|
|
@ -701,6 +701,7 @@ struct GowinGlobalRouter
|
||||||
log_info(" '%s' net was routed using global resources %s.\n", ctx->nameOf(net),
|
log_info(" '%s' net was routed using global resources %s.\n", ctx->nameOf(net),
|
||||||
route_result == ROUTED_ALL ? "only" : "partially");
|
route_result == ROUTED_ALL ? "only" : "partially");
|
||||||
}
|
}
|
||||||
|
return route_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// segmented wires
|
// segmented wires
|
||||||
|
|
@ -1303,7 +1304,12 @@ struct GowinGlobalRouter
|
||||||
if (ctx->verbose) {
|
if (ctx->verbose) {
|
||||||
log_info("route clock net '%s', src:%s\n", ctx->nameOf(ni), ctx->nameOf(ni->driver.cell));
|
log_info("route clock net '%s', src:%s\n", ctx->nameOf(ni), ctx->nameOf(ni->driver.cell));
|
||||||
}
|
}
|
||||||
route_clk_net(ni);
|
if (route_clk_net(ni) == NOT_ROUTED) {
|
||||||
|
if (ctx->verbose) {
|
||||||
|
log_info(" try to route as a segmented network.\n");
|
||||||
|
}
|
||||||
|
seg_nets.push_back(net_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// segmented nets
|
// segmented nets
|
||||||
|
|
|
||||||
|
|
@ -1512,15 +1512,16 @@ def create_timing_info(chip: Chip, db: chipdb.Device):
|
||||||
elif group == "fanout":
|
elif group == "fanout":
|
||||||
pass # handled in "wire"
|
pass # handled in "wire"
|
||||||
elif group == "glbsrc":
|
elif group == "glbsrc":
|
||||||
# TODO
|
|
||||||
# no fanout delay for clock wires
|
# no fanout delay for clock wires
|
||||||
for name in ["CENT_SPINE_PCLK", "SPINE_TAP_PCLK", "TAP_BRANCH_PCLK"]:
|
for name in ["CENT_SPINE_PCLK", "SPINE_TAP_PCLK", "TAP_BRANCH_PCLK"]:
|
||||||
tmg.set_pip_class(speed, name, group_to_timingvalue(arc[name]))
|
tmg.set_pip_class(speed, name, group_to_timingvalue(arc[name]))
|
||||||
tmg.set_pip_class(speed, 'GCLK_BRANCH', group_to_timingvalue(arc['BRANCH_PCLK']))
|
tmg.set_pip_class(speed, 'GCLK_BRANCH', group_to_timingvalue(arc['BRANCH_PCLK']))
|
||||||
elif group == "hclk":
|
elif group == "hclk":
|
||||||
pass # TODO
|
for name in ['HclkInMux', 'HclkHbrgMux', 'HclkOutMux', 'HclkDivMux']:
|
||||||
|
tmg.set_pip_class(speed, name, group_to_timingvalue(arc[name]))
|
||||||
elif group == "iodelay":
|
elif group == "iodelay":
|
||||||
pass # TODO
|
for name in ['GI_DO', 'SDTAP_DO', 'SETN_DO', 'VALUE_DO', 'SDTAP_DF', 'SETN_DF', 'VALUE_DF']:
|
||||||
|
tmg.set_pip_class(speed, name, group_to_timingvalue(arc[name]))
|
||||||
elif group == "wire":
|
elif group == "wire":
|
||||||
# wires with delay and fanout delay
|
# wires with delay and fanout delay
|
||||||
for name in ["X0", "X2", "X8"]:
|
for name in ["X0", "X2", "X8"]:
|
||||||
|
|
@ -1529,7 +1530,7 @@ def create_timing_info(chip: Chip, db: chipdb.Device):
|
||||||
for name in ["X0CTL", "X0CLK", "FX1"]:
|
for name in ["X0CTL", "X0CLK", "FX1"]:
|
||||||
tmg.set_pip_class(speed, name, group_to_timingvalue(arc[name]))
|
tmg.set_pip_class(speed, name, group_to_timingvalue(arc[name]))
|
||||||
# wires with presently-unknown delay
|
# wires with presently-unknown delay
|
||||||
for name in ["LUT_IN", "DI", "SEL", "CIN", "COUT", "VCC", "VSS", "LW_TAP", "LW_TAP_0", "LW_BRANCH", "LW_SPAN"]:
|
for name in ["LUT_IN", "DI", "SEL", "CIN", "COUT", "VCC", "VSS", "LW_TAP", "LW_TAP_0", "LW_BRANCH", "LW_SPAN", "ISB"]:
|
||||||
tmg.set_pip_class(speed, name, TimingValue())
|
tmg.set_pip_class(speed, name, TimingValue())
|
||||||
# wires with fanout-only delay; used on cell output pips
|
# wires with fanout-only delay; used on cell output pips
|
||||||
for name, mapping in [("LUT_OUT", "FFan"), ("FF_OUT", "QFan"), ("OF", "OFFan")]:
|
for name, mapping in [("LUT_OUT", "FFan"), ("FF_OUT", "QFan"), ("OF", "OFFan")]:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue