Skip to content

Commit

Permalink
Gowin. Implement the EMCU primitive. (YosysHQ#1366)
Browse files Browse the repository at this point in the history
* Gowin. Implement the EMCU primitive.

Add support for the GW1NSR-4C's embedded Cortex-M3 processor. Since it
uses flash in its own way, we disable additional flash processing for
this case.

Signed-off-by: YRabbit <[email protected]>

* Gowin. Fix merge.

Signed-off-by: YRabbit <[email protected]>

---------

Signed-off-by: YRabbit <[email protected]>
  • Loading branch information
yrabbit authored Sep 12, 2024
1 parent ff7b853 commit 50bd8d0
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 5 deletions.
3 changes: 3 additions & 0 deletions himbaechel/uarch/gowin/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1289,3 +1289,6 @@ X(RESETN)
//HCLK Parameters
X(DIV_MODE)
X(GSREN)

// EMCU
X(EMCU)
7 changes: 6 additions & 1 deletion himbaechel/uarch/gowin/gowin.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ inline bool type_is_userflash(IdString cell_type)
}
inline bool is_userflash(const CellInfo *cell) { return type_is_userflash(cell->type); }

// Return true if a cell is a EMCU
inline bool type_is_emcu(IdString cell_type) { return cell_type == id_EMCU; }
inline bool is_emcu(const CellInfo *cell) { return type_is_emcu(cell->type); }

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


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

USERFLASH_Z = 298,

EMCU_Z = 300,

// 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
15 changes: 15 additions & 0 deletions himbaechel/uarch/gowin/gowin_arch_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
USERFLASH_Z = 298


EMCU_Z = 300

DSP_Z = 509

DSP_0_Z = 511 # DSP macro 0
Expand Down Expand Up @@ -585,6 +587,19 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
if not tt.has_wire(wire):
tt.create_wire(wire, "FLASH_OUT")
tt.add_bel_pin(bel, port, wire, PinType.OUTPUT)
elif func == 'emcu':
bel = tt.create_bel("EMCU", "EMCU", EMCU_Z)
portmap = desc['ins']
for port, wire in portmap.items():
print(port, wire)
if not tt.has_wire(wire):
tt.create_wire(wire, "EMCU_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, "EMCU_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
122 changes: 118 additions & 4 deletions himbaechel/uarch/gowin/pack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3094,7 +3094,7 @@ 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(),
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))) {
Expand All @@ -3109,7 +3109,7 @@ struct GowinPacker
// =========================================
// Enable UserFlash
// =========================================
void pack_userflash()
void pack_userflash(bool have_emcu)
{
log_info("Pack UserFlash cells...\n");
std::vector<std::unique_ptr<CellInfo>> new_cells;
Expand Down Expand Up @@ -3152,6 +3152,11 @@ struct GowinPacker
ci.renamePort(ctx->idf("YADR[%d]", i), ctx->idf("YADR%d", i));
}
}

if (have_emcu) {
continue;
}

// add invertor
int lut_idx = 0;
auto add_inv = [&](IdString port, PortType port_type) {
Expand Down Expand Up @@ -3196,6 +3201,115 @@ struct GowinPacker
}
}

// =========================================
// Create EMCU
// =========================================
void pack_emcu_and_flash()
{
log_info("Pack EMCU and UserFlash cells...\n");
std::vector<std::unique_ptr<CellInfo>> new_cells;

bool have_emcu = false;
for (auto &cell : ctx->cells) {
auto &ci = *cell.second;
if (!is_emcu(&ci)) {
continue;
}
have_emcu = true;

// rename ports
for (int i = 0; i < 2; ++i) {
ci.renamePort(ctx->idf("TARGFLASH0HTRANS[%d]", i), ctx->idf("TARGFLASH0HTRANS%d", i));
ci.renamePort(ctx->idf("TARGEXP0HTRANS[%d]", i), ctx->idf("TARGEXP0HTRANS%d", i));
ci.renamePort(ctx->idf("TARGEXP0MEMATTR[%d]", i), ctx->idf("TARGEXP0MEMATTR%d", i));
// ins
ci.renamePort(ctx->idf("INITEXP0HTRANS[%d]", i), ctx->idf("INITEXP0HTRANS%d", i));
ci.renamePort(ctx->idf("INITEXP0MEMATTR[%d]", i), ctx->idf("INITEXP0MEMATTR%d", i));
}
for (int i = 0; i < 3; ++i) {
ci.renamePort(ctx->idf("TARGEXP0HSIZE[%d]", i), ctx->idf("TARGEXP0HSIZE%d", i));
ci.renamePort(ctx->idf("TARGEXP0HBURST[%d]", i), ctx->idf("TARGEXP0HBURST%d", i));
ci.renamePort(ctx->idf("APBTARGEXP2PPROT[%d]", i), ctx->idf("APBTARGEXP2PPROT%d", i));
// ins
ci.renamePort(ctx->idf("TARGEXP0HRUSER[%d]", i), ctx->idf("TARGEXP0HRUSER%d", i));
ci.renamePort(ctx->idf("INITEXP0HSIZE[%d]", i), ctx->idf("INITEXP0HSIZE%d", i));
ci.renamePort(ctx->idf("INITEXP0HBURST[%d]", i), ctx->idf("INITEXP0HBURST%d", i));
}
for (int i = 0; i < 4; ++i) {
ci.renamePort(ctx->idf("SRAM0WREN[%d]", i), ctx->idf("SRAM0WREN%d", i));
ci.renamePort(ctx->idf("TARGEXP0HPROT[%d]", i), ctx->idf("TARGEXP0HPROT%d", i));
ci.renamePort(ctx->idf("TARGEXP0HMASTER[%d]", i), ctx->idf("TARGEXP0HMASTER%d", i));
ci.renamePort(ctx->idf("APBTARGEXP2PSTRB[%d]", i), ctx->idf("APBTARGEXP2PSTRB%d", i));
ci.renamePort(ctx->idf("TPIUTRACEDATA[%d]", i), ctx->idf("TPIUTRACEDATA%d", i));
// ins
ci.renamePort(ctx->idf("INITEXP0HPROT[%d]", i), ctx->idf("INITEXP0HPROT%d", i));
ci.renamePort(ctx->idf("INITEXP0HMASTER[%d]", i), ctx->idf("INITEXP0HMASTER%d", i));
ci.renamePort(ctx->idf("INITEXP0HWUSER[%d]", i), ctx->idf("INITEXP0HWUSER%d", i));
}
for (int i = 0; i < 16; ++i) {
if (i < 13) {
if (i < 12) {
if (i < 5) {
ci.renamePort(ctx->idf("GPINT[%d]", i), ctx->idf("GPINT%d", i));
}
ci.renamePort(ctx->idf("APBTARGEXP2PADDR[%d]", i), ctx->idf("APBTARGEXP2PADDR%d", i));
}
ci.renamePort(ctx->idf("SRAM0ADDR[%d]", i), ctx->idf("SRAM0ADDR%d", i));
}
ci.renamePort(ctx->idf("IOEXPOUTPUTO[%d]", i), ctx->idf("IOEXPOUTPUTO%d", i));
ci.renamePort(ctx->idf("IOEXPOUTPUTENO[%d]", i), ctx->idf("IOEXPOUTPUTENO%d", i));
// ins
ci.renamePort(ctx->idf("IOEXPINPUTI[%d]", i), ctx->idf("IOEXPINPUTI%d", i));
}
for (int i = 0; i < 32; ++i) {
if (i < 29) {
ci.renamePort(ctx->idf("TARGFLASH0HADDR[%d]", i), ctx->idf("TARGFLASH0HADDR%d", i));
}
ci.renamePort(ctx->idf("SRAM0WDATA[%d]", i), ctx->idf("SRAM0WDATA%d", i));
ci.renamePort(ctx->idf("TARGEXP0HADDR[%d]", i), ctx->idf("TARGEXP0HADDR%d", i));
ci.renamePort(ctx->idf("TARGEXP0HWDATA[%d]", i), ctx->idf("TARGEXP0HWDATA%d", i));
ci.renamePort(ctx->idf("INITEXP0HRDATA[%d]", i), ctx->idf("INITEXP0HRDATA%d", i));
ci.renamePort(ctx->idf("APBTARGEXP2PWDATA[%d]", i), ctx->idf("APBTARGEXP2PWDATA%d", i));
// ins
ci.renamePort(ctx->idf("SRAM0RDATA[%d]", i), ctx->idf("SRAM0RDATA%d", i));
ci.renamePort(ctx->idf("TARGEXP0HRDATA[%d]", i), ctx->idf("TARGEXP0HRDATA%d", i));
ci.renamePort(ctx->idf("INITEXP0HADDR[%d]", i), ctx->idf("INITEXP0HADDR%d", i));
ci.renamePort(ctx->idf("INITEXP0HWDATA[%d]", i), ctx->idf("INITEXP0HWDATA%d", i));
ci.renamePort(ctx->idf("APBTARGEXP2PRDATA[%d]", i), ctx->idf("APBTARGEXP2PRDATA%d", i));
}
// The flash data bus is connected directly to the CPU so just disconnect these networks
// also other non-switched networks
ci.disconnectPort(ctx->id("DAPNTDOEN"));
ci.disconnectPort(ctx->id("DAPNTRST"));
ci.disconnectPort(ctx->id("DAPTDO"));
ci.disconnectPort(ctx->id("DAPTDI"));
ci.disconnectPort(ctx->id("TARGFLASH0HREADYMUX"));
ci.disconnectPort(ctx->id("TARGEXP0HAUSER"));
ci.disconnectPort(ctx->id("TARGFLASH0EXRESP"));
ci.disconnectPort(ctx->id("PORESETN"));
ci.disconnectPort(ctx->id("SYSRESETN"));
ci.disconnectPort(ctx->id("DAPSWDITMS"));
ci.disconnectPort(ctx->id("DAPSWCLKTCK"));
ci.disconnectPort(ctx->id("TPIUTRACECLK"));
for (int i = 0; i < 32; ++i) {
if (i < 4) {
if (i < 3) {
ci.disconnectPort(ctx->idf("TARGFLASH0HSIZE[%d]", i));
ci.disconnectPort(ctx->idf("TARGFLASH0HBURST[%d]", i));
ci.disconnectPort(ctx->idf("TARGFLASH0HRUSER[%d]", i));
ci.disconnectPort(ctx->idf("INITEXP0HRUSER[%d]", i));
}
// ci.disconnectPort(ctx->idf("TARGFLASH0HPROT[%d]", i));
ci.disconnectPort(ctx->idf("TARGEXP0HWUSER[%d]", i));
ci.disconnectPort(ctx->idf("MTXREMAP[%d]", i));
}
// ins
ci.disconnectPort(ctx->idf("TARGFLASH0HRDATA[%d]", i));
}
}
pack_userflash(have_emcu);
}

void run(void)
{
handle_constants();
Expand Down Expand Up @@ -3248,10 +3362,10 @@ struct GowinPacker
pack_buffered_nets();
ctx->check();

pack_dhcens();
pack_emcu_and_flash();
ctx->check();

pack_userflash();
pack_dhcens();
ctx->check();

pack_dqce();
Expand Down

0 comments on commit 50bd8d0

Please sign in to comment.