Gowin. Implement power saving primitive
As the board on the GW1N-1 chip becomes a rarity, its replacement is the Tangnano1k board with the GW1NZ-1 chip. This chip has a unique mechanism for turning off power to important things such as OSC, PLL, etc. Here we introduce a primitive that allows energy saving to be controlled dynamically. We also bring the names of some functions to uniformity. Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
ba293437e0
commit
7dd4a8c1d5
@ -987,6 +987,10 @@ X(GSR)
|
||||
X(GSR0)
|
||||
X(GSRI)
|
||||
|
||||
// power saving
|
||||
X(BANDGAP)
|
||||
X(BGEN)
|
||||
|
||||
// inverter
|
||||
X(INV)
|
||||
|
||||
|
@ -259,7 +259,7 @@ void GowinImpl::adjust_dsp_pin_mapping(void)
|
||||
void GowinImpl::prePlace() { assign_cell_info(); }
|
||||
void GowinImpl::postPlace()
|
||||
{
|
||||
gwu.have_SP32();
|
||||
gwu.has_SP32();
|
||||
if (ctx->debug) {
|
||||
log_info("================== Final Placement ===================\n");
|
||||
for (auto &cell : ctx->cells) {
|
||||
|
@ -99,6 +99,7 @@ NPNR_PACKED_STRUCT(struct Extra_chip_data_POD {
|
||||
static constexpr int32_t NEED_SP_FIX = 2;
|
||||
static constexpr int32_t NEED_BSRAM_OUTREG_FIX = 4;
|
||||
static constexpr int32_t NEED_BLKSEL_FIX = 8;
|
||||
static constexpr int32_t HAS_BANDGAP = 16;
|
||||
});
|
||||
|
||||
} // namespace
|
||||
@ -131,6 +132,7 @@ enum
|
||||
GSR_Z = 276,
|
||||
VCC_Z = 277,
|
||||
VSS_Z = 278,
|
||||
BANDGAP_Z = 279,
|
||||
|
||||
// The two least significant bits encode Z for 9-bit adders and
|
||||
// multipliers, if they are equal to 0, then we get Z of their common
|
||||
|
@ -19,6 +19,7 @@ CHIP_HAS_SP32 = 0x1
|
||||
CHIP_NEED_SP_FIX = 0x2
|
||||
CHIP_NEED_BSRAM_OUTREG_FIX = 0x4
|
||||
CHIP_NEED_BLKSEL_FIX = 0x8
|
||||
CHIP_HAS_BANDGAP = 0x10
|
||||
|
||||
# Z of the bels
|
||||
# sync with C++ part!
|
||||
@ -46,6 +47,7 @@ PLL_Z = 275
|
||||
GSR_Z = 276
|
||||
VCC_Z = 277
|
||||
GND_Z = 278
|
||||
BANDGAP_Z = 279
|
||||
|
||||
DSP_Z = 509
|
||||
|
||||
@ -338,6 +340,11 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
|
||||
tt.create_wire(wire, "GSRI")
|
||||
bel = tt.create_bel("GSR", "GSR", z = GSR_Z)
|
||||
tt.add_bel_pin(bel, "GSRI", wire, PinType.INPUT)
|
||||
elif func == 'bandgap':
|
||||
wire = desc['wire']
|
||||
tt.create_wire(wire, "BGEN")
|
||||
bel = tt.create_bel("BANDGAP", "BANDGAP", z = BANDGAP_Z)
|
||||
tt.add_bel_pin(bel, "BGEN", wire, PinType.INPUT)
|
||||
if func == 'io16':
|
||||
role = desc['role']
|
||||
if role == 'MAIN':
|
||||
@ -1024,6 +1031,8 @@ def main():
|
||||
chip_flags |= CHIP_NEED_BSRAM_OUTREG_FIX;
|
||||
if "NEED_BLKSEL_FIX" in db.chip_flags:
|
||||
chip_flags |= CHIP_NEED_BLKSEL_FIX;
|
||||
if "HAS_BANDGAP" in db.chip_flags:
|
||||
chip_flags |= CHIP_HAS_BANDGAP;
|
||||
|
||||
X = db.cols;
|
||||
Y = db.rows;
|
||||
|
@ -94,7 +94,7 @@ bool GowinUtils::is_diff_io_supported(IdString type)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GowinUtils::have_bottom_io_cnds(void)
|
||||
bool GowinUtils::has_bottom_io_cnds(void)
|
||||
{
|
||||
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
|
||||
return extra->bottom_io.conditions.size() != 0;
|
||||
@ -112,7 +112,13 @@ IdString GowinUtils::get_bottom_io_wire_b_net(int8_t condition)
|
||||
return IdString(extra->bottom_io.conditions[condition].wire_b_net);
|
||||
}
|
||||
|
||||
bool GowinUtils::have_SP32(void)
|
||||
bool GowinUtils::has_BANDGAP(void)
|
||||
{
|
||||
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
|
||||
return extra->chip_flags & Extra_chip_data_POD::HAS_BANDGAP;
|
||||
}
|
||||
|
||||
bool GowinUtils::has_SP32(void)
|
||||
{
|
||||
const Extra_chip_data_POD *extra = reinterpret_cast<const Extra_chip_data_POD *>(ctx->chip_info->extra_data.get());
|
||||
return extra->chip_flags & Extra_chip_data_POD::HAS_SP32;
|
||||
|
@ -35,11 +35,14 @@ struct GowinUtils
|
||||
BelId get_io_bel_from_iologic(BelId bel);
|
||||
|
||||
// BSRAM
|
||||
bool have_SP32(void);
|
||||
bool has_SP32(void);
|
||||
bool need_SP_fix(void);
|
||||
bool need_BSRAM_OUTREG_fix(void);
|
||||
bool need_BLKSEL_fix(void);
|
||||
|
||||
// Power saving
|
||||
bool has_BANDGAP(void);
|
||||
|
||||
// DSP
|
||||
inline int get_dsp_18_z(int z) const { return z & (~3); }
|
||||
inline int get_dsp_9_idx(int z) const { return z & 3; }
|
||||
@ -65,7 +68,7 @@ struct GowinUtils
|
||||
CellInfo *dsp_bus_dst(const CellInfo *ci, const char *bus_prefix, int wire_num) const;
|
||||
|
||||
bool is_diff_io_supported(IdString type);
|
||||
bool have_bottom_io_cnds(void);
|
||||
bool has_bottom_io_cnds(void);
|
||||
IdString get_bottom_io_wire_a_net(int8_t condition);
|
||||
IdString get_bottom_io_wire_b_net(int8_t condition);
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct GowinPacker
|
||||
|
||||
void config_bottom_row(CellInfo &ci, Loc loc, uint8_t cnd = Bottom_io_POD::NORMAL)
|
||||
{
|
||||
if (!gwu.have_bottom_io_cnds()) {
|
||||
if (!gwu.has_bottom_io_cnds()) {
|
||||
return;
|
||||
}
|
||||
if (!ci.type.in(id_OBUF, id_TBUF, id_IOBUF)) {
|
||||
@ -1802,7 +1802,7 @@ struct GowinPacker
|
||||
// For GW1N-9/GW1NR-9/GW1NS-4 series, 32/36-bit SP/SPX9 is divided into two
|
||||
// SP/SPX9s, which occupy two BSRAMs.
|
||||
// So divide it here
|
||||
if ((bit_width == 32 || bit_width == 36) && !gwu.have_SP32()) {
|
||||
if ((bit_width == 32 || bit_width == 36) && !gwu.has_SP32()) {
|
||||
divide_sp(ci, new_cells);
|
||||
bit_width = ci->params.at(id_BIT_WIDTH).as_int64();
|
||||
}
|
||||
@ -2839,6 +2839,41 @@ struct GowinPacker
|
||||
}
|
||||
}
|
||||
|
||||
// ===================================
|
||||
// Global power regulator
|
||||
// ===================================
|
||||
void pack_bandgap(void)
|
||||
{
|
||||
if (!gwu.has_BANDGAP()) {
|
||||
return;
|
||||
}
|
||||
log_info("Pack BANDGAP...\n");
|
||||
|
||||
bool user_bandgap = false;
|
||||
for (auto &cell : ctx->cells) {
|
||||
auto &ci = *cell.second;
|
||||
|
||||
if (ci.type == id_BANDGAP) {
|
||||
user_bandgap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!user_bandgap) {
|
||||
// make default BANDGAP
|
||||
auto bandgap_cell = std::make_unique<CellInfo>(ctx, id_BANDGAP, id_BANDGAP);
|
||||
bandgap_cell->addInput(id_BGEN);
|
||||
bandgap_cell->connectPort(id_BGEN, ctx->nets.at(ctx->id("$PACKER_VCC")).get());
|
||||
ctx->cells[bandgap_cell->name] = std::move(bandgap_cell);
|
||||
}
|
||||
if (ctx->verbose) {
|
||||
if (user_bandgap) {
|
||||
log_info("Have user BANDGAP\n");
|
||||
} else {
|
||||
log_info("No user BANDGAP. Make one.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===================================
|
||||
// Replace INV with LUT
|
||||
// ===================================
|
||||
@ -2957,6 +2992,9 @@ struct GowinPacker
|
||||
pack_gsr();
|
||||
ctx->check();
|
||||
|
||||
pack_bandgap();
|
||||
ctx->check();
|
||||
|
||||
pack_wideluts();
|
||||
ctx->check();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user