Skip to content

Commit

Permalink
Gowin. Implement power saving primitive
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
yrabbit authored and gatecat committed Jul 8, 2024
1 parent ba29343 commit 7dd4a8c
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 7 deletions.
4 changes: 4 additions & 0 deletions himbaechel/uarch/gowin/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,10 @@ X(GSR)
X(GSR0)
X(GSRI)

// power saving
X(BANDGAP)
X(BGEN)

// inverter
X(INV)

Expand Down
2 changes: 1 addition & 1 deletion himbaechel/uarch/gowin/gowin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions himbaechel/uarch/gowin/gowin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions himbaechel/uarch/gowin/gowin_arch_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
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!
Expand Down Expand Up @@ -46,6 +47,7 @@
GSR_Z = 276
VCC_Z = 277
GND_Z = 278
BANDGAP_Z = 279

DSP_Z = 509

Expand Down Expand Up @@ -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':
Expand Down Expand Up @@ -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;
Expand Down
10 changes: 8 additions & 2 deletions himbaechel/uarch/gowin/gowin_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions himbaechel/uarch/gowin/gowin_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -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);

Expand Down
42 changes: 40 additions & 2 deletions himbaechel/uarch/gowin/pack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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
// ===================================
Expand Down Expand Up @@ -2957,6 +2992,9 @@ struct GowinPacker
pack_gsr();
ctx->check();

pack_bandgap();
ctx->check();

pack_wideluts();
ctx->check();

Expand Down

0 comments on commit 7dd4a8c

Please sign in to comment.