Skip to content

Commit

Permalink
Merge branch 'master' into dhcen
Browse files Browse the repository at this point in the history
  • Loading branch information
yrabbit authored Sep 4, 2024
2 parents 419f264 + 4cf7afe commit e1aab4b
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 3 deletions.
37 changes: 36 additions & 1 deletion himbaechel/uarch/gowin/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,42 @@ X(BOTTOM_IO_PORT_A)
X(BOTTOM_IO_PORT_B)
X(IOLOGIC_DUMMY)

//
// User Flash
X(INUSEN)
X(DIN)
X(DOUT)
X(XE)
X(YE)
X(SE)
X(PROG)
X(ERASE)
X(NVSTR)
X(XADR0)
X(XADR1)
X(XADR2)
X(XADR3)
X(XADR4)
X(XADR5)
X(XADR6)
X(XADR7)
X(XADR8)
X(YADR)
X(RA)
X(CA)
X(PA)
X(MODE)
X(SEQ)
X(RMODE)
X(WMODE)
X(RBYTESEL)
X(WBYTESEL)
X(FLASH96K)
X(FLASH256K)
X(FLASH608K)
X(FLASH128K)
X(FLASH64K)
X(FLASH64KZ)
X(FLASH96KA)

// wire types
X(GLOBAL_CLK)
Expand Down
13 changes: 12 additions & 1 deletion himbaechel/uarch/gowin/gowin.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ inline bool is_clkdiv2(const CellInfo *cell) { return type_is_clkdiv2(cell->type
// Return true for HCLK Cells
inline bool is_hclk(const CellInfo *cell) { return type_is_clkdiv2(cell->type) || type_is_clkdiv(cell->type); }

// Return true if a cell is a UserFlash
inline bool type_is_userflash(IdString cell_type)
{
return cell_type.in(id_FLASH96K, id_FLASH256K, id_FLASH608K, id_FLASH128K, id_FLASH64K, id_FLASH64K, id_FLASH64KZ,
id_FLASH96KA);
}
inline bool is_userflash(const CellInfo *cell) { return type_is_userflash(cell->type); }

// ==========================================
// extra data in the chip db
// ==========================================
Expand Down Expand Up @@ -165,10 +173,13 @@ enum
VSS_Z = 278,
BANDGAP_Z = 279,


DQCE_Z = 280, // : 286 reserve for 6 DQCEs
DCS_Z = 286, // : 287 reserve for 2 DCSs
DCS_Z = 286, // : 288 reserve for 2 DCSs
DHCEN_Z = 288, // : 298

USERFLASH_Z = 298,

// 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
// 18-bit equivalent.
Expand Down
17 changes: 16 additions & 1 deletion himbaechel/uarch/gowin/gowin_arch_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@
BANDGAP_Z = 279

DQCE_Z = 280 # : 286 reserve for 6 DQCEs
DCS_Z = 286 # : 287 reserve for 2 DCSs
DCS_Z = 286 # : 288 reserve for 2 DCSs
DHCEN_Z = 288 # : 298

USERFLASH_Z = 298


DSP_Z = 509

DSP_0_Z = 511 # DSP macro 0
Expand Down Expand Up @@ -570,6 +573,18 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
bel.flags = BEL_FLAG_GLOBAL
tt.add_bel_pin(bel, "I", wire, PinType.INPUT)
tt.add_bel_pin(bel, "O", wire_out, PinType.OUTPUT)
elif func == 'userflash':
bel = tt.create_bel("USERFLASH", desc['type'], USERFLASH_Z)
portmap = desc['ins']
for port, wire in portmap.items():
if not tt.has_wire(wire):
tt.create_wire(wire, "FLASH_IN")
tt.add_bel_pin(bel, port, wire, PinType.INPUT)
portmap = desc['outs']
for port, wire in portmap.items():
if not tt.has_wire(wire):
tt.create_wire(wire, "FLASH_OUT")
tt.add_bel_pin(bel, port, wire, PinType.OUTPUT)

def create_tiletype(create_func, chip: Chip, db: chipdb, x: int, y: int, ttyp: int):
has_extra_func = (y, x) in db.extra_func
Expand Down
101 changes: 101 additions & 0 deletions himbaechel/uarch/gowin/pack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3006,6 +3006,8 @@ struct GowinPacker
// =========================================
void pack_dqce()
{
log_info("Pack DQCE cells...\n");

// At the placement stage, nothing can be said definitively about DQCE,
// so we make user cells virtual but allocate all available bels by
// creating and placing cells - we will use some of them after, and
Expand Down Expand Up @@ -3039,6 +3041,8 @@ struct GowinPacker
// =========================================
void pack_dcs()
{
log_info("Pack DCS cells...\n");

// At the placement stage, nothing can be said definitively about DCS,
// so we make user cells virtual but allocate all available bels by
// creating and placing cells - we will use some of them after, and
Expand Down Expand Up @@ -3088,6 +3092,10 @@ struct GowinPacker
}
}
if (grab_bels) {
// sane message if new primitives are used with old bases
auto buckets = ctx->getBelBuckets();
NPNR_ASSERT_MSG(std::find(buckets.begin(), buckets.end(), id_DHCEN) != buckets.end(),
"There are no DHCEN bels to use.");
int i = 0;
for (auto &bel : ctx->getBelsInBucket(ctx->getBelBucketForCellType(id_DHCEN))) {
IdString dhcen_name = ctx->idf("$PACKER_DHCEN_%d", ++i);
Expand All @@ -3098,6 +3106,96 @@ struct GowinPacker
}
}

// =========================================
// Enable UserFlash
// =========================================
void pack_userflash()
{
log_info("Pack UserFlash cells...\n");
std::vector<std::unique_ptr<CellInfo>> new_cells;

for (auto &cell : ctx->cells) {
auto &ci = *cell.second;
if (!is_userflash(&ci)) {
continue;
}

if (ci.type.in(id_FLASH96K, id_FLASH256K, id_FLASH608K)) {
// enable
ci.addInput(id_INUSEN);
ci.connectPort(id_INUSEN, ctx->nets.at(ctx->id("$PACKER_GND")).get());
}
// rename ports
for (int i = 0; i < 32; ++i) {
ci.renamePort(ctx->idf("DIN[%d]", i), ctx->idf("DIN%d", i));
ci.renamePort(ctx->idf("DOUT[%d]", i), ctx->idf("DOUT%d", i));
}
if (ci.type.in(id_FLASH96K)) {
for (int i = 0; i < 6; ++i) {
ci.renamePort(ctx->idf("RA[%d]", i), ctx->idf("RA%d", i));
ci.renamePort(ctx->idf("CA[%d]", i), ctx->idf("CA%d", i));
ci.renamePort(ctx->idf("PA[%d]", i), ctx->idf("PA%d", i));
}
for (int i = 0; i < 2; ++i) {
ci.renamePort(ctx->idf("MODE[%d]", i), ctx->idf("MODE%d", i));
ci.renamePort(ctx->idf("SEQ[%d]", i), ctx->idf("SEQ%d", i));
ci.renamePort(ctx->idf("RMODE[%d]", i), ctx->idf("RMODE%d", i));
ci.renamePort(ctx->idf("WMODE[%d]", i), ctx->idf("WMODE%d", i));
ci.renamePort(ctx->idf("RBYTESEL[%d]", i), ctx->idf("RBYTESEL%d", i));
ci.renamePort(ctx->idf("WBYTESEL[%d]", i), ctx->idf("WBYTESEL%d", i));
}
} else {
for (int i = 0; i < 9; ++i) {
ci.renamePort(ctx->idf("XADR[%d]", i), ctx->idf("XADR%d", i));
}
for (int i = 0; i < 6; ++i) {
ci.renamePort(ctx->idf("YADR[%d]", i), ctx->idf("YADR%d", i));
}
}
// add invertor
int lut_idx = 0;
auto add_inv = [&](IdString port, PortType port_type) {
if (!port_used(&ci, port)) {
return;
}

std::unique_ptr<CellInfo> lut_cell =
gwu.create_cell(create_aux_name(ci.name, lut_idx, "_lut$"), id_LUT4);
new_cells.push_back(std::move(lut_cell));
CellInfo *lut = new_cells.back().get();
lut->addInput(id_I0);
lut->addOutput(id_F);
lut->setParam(id_INIT, 0x5555);
++lut_idx;

if (port_type == PORT_IN) {
ci.movePortTo(port, lut, id_I0);
lut->connectPorts(id_F, &ci, port);
} else {
ci.movePortTo(port, lut, id_F);
ci.connectPorts(port, lut, id_I0);
}
};
for (auto pin : ci.ports) {
if (pin.second.type == PORT_OUT) {
add_inv(pin.first, PORT_OUT);
} else {
if (pin.first == id_INUSEN) {
continue;
}
if (ci.type == id_FLASH608K && pin.first.in(id_XADR0, id_XADR1, id_XADR2, id_XADR3, id_XADR4,
id_XADR5, id_XADR6, id_XADR7, id_XADR8)) {
continue;
}
add_inv(pin.first, PORT_IN);
}
}
}
for (auto &ncell : new_cells) {
ctx->cells[ncell->name] = std::move(ncell);
}
}

void run(void)
{
handle_constants();
Expand Down Expand Up @@ -3153,6 +3251,9 @@ struct GowinPacker
pack_dhcens();
ctx->check();

pack_userflash();
ctx->check();

pack_dqce();
ctx->check();

Expand Down

0 comments on commit e1aab4b

Please sign in to comment.