@@ -308,6 +308,47 @@ struct GowinPacker
308
308
}
309
309
}
310
310
311
+ // ===================================
312
+ // I3C
313
+ // ===================================
314
+ void pack_i3c (void )
315
+ {
316
+ log_info (" Pack I3C IOs...\n " );
317
+ std::vector<IdString> cells_to_remove;
318
+
319
+ for (auto &cell : ctx->cells ) {
320
+ CellInfo &ci = *cell.second ;
321
+ if (!is_i3c (&ci)) {
322
+ continue ;
323
+ }
324
+ // check for I3C-capable pin A
325
+ CellInfo *iob = net_only_drives (ctx, ci.ports .at (id_IO).net , is_iob, id_I);
326
+ if (iob == nullptr || iob->bel == BelId ()) {
327
+ log_error (" I3C %s IO is not connected to the input pin or the pin is not constrained.\n " ,
328
+ ctx->nameOf (&ci));
329
+ }
330
+ BelId iob_bel = iob->bel ;
331
+ Loc iob_loc = ctx->getBelLocation (iob_bel);
332
+
333
+ if (!gwu.get_i3c_capable (iob_loc.x , iob_loc.y )) {
334
+ log_error (" Can't place %s. Not I3C capable X%dY%d.\n " , ctx->nameOf (&ci), iob_loc.x , iob_loc.y );
335
+ }
336
+ ci.disconnectPort (id_IO);
337
+ iob->disconnectPort (id_I);
338
+ ci.movePortTo (id_I, iob, id_I);
339
+ ci.movePortTo (id_O, iob, id_O);
340
+ iob->disconnectPort (id_OEN);
341
+ ci.movePortTo (id_MODESEL, iob, id_OEN);
342
+
343
+ iob->setParam (id_I3C_IOBUF, 1 );
344
+ cells_to_remove.push_back (ci.name );
345
+ }
346
+
347
+ for (auto cell : cells_to_remove) {
348
+ ctx->cells .erase (cell);
349
+ }
350
+ }
351
+
311
352
// ===================================
312
353
// MIPI IO
313
354
// ===================================
@@ -330,6 +371,9 @@ struct GowinPacker
330
371
log_error (" MIPI %s is not connected to the output pin or the pin is not constrained.\n " ,
331
372
ctx->nameOf (&ci));
332
373
}
374
+ if (out_iob->params .count (id_I3C_IOBUF)) {
375
+ log_error (" Can't place MIPI %s. Conflict with I3C %s.\n " , ctx->nameOf (&ci), ctx->nameOf (out_iob));
376
+ }
333
377
BelId iob_bel = out_iob->bel ;
334
378
Loc iob_loc = ctx->getBelLocation (iob_bel);
335
379
iob_loc.z = BelZ::MIPIOBUF_Z;
@@ -383,6 +427,9 @@ struct GowinPacker
383
427
ctx->nameOf (&ci));
384
428
}
385
429
// check A IO placing
430
+ if (in_iob->params .count (id_I3C_IOBUF)) {
431
+ log_error (" Can't place MIPI %s. Conflict with I3C %s.\n " , ctx->nameOf (&ci), ctx->nameOf (in_iob));
432
+ }
386
433
BelId iob_bel = in_iob->bel ;
387
434
Loc iob_loc = ctx->getBelLocation (iob_bel);
388
435
if (iob_loc.z != BelZ::IOBA_Z) {
@@ -402,6 +449,9 @@ struct GowinPacker
402
449
ctx->nameOf (&ci));
403
450
}
404
451
// check B IO placing
452
+ if (inb_iob->params .count (id_I3C_IOBUF)) {
453
+ log_error (" Can't place MIPI %s. Conflict with I3C %s.\n " , ctx->nameOf (&ci), ctx->nameOf (inb_iob));
454
+ }
405
455
BelId iobb_bel = inb_iob->bel ;
406
456
Loc iobb_loc = ctx->getBelLocation (iobb_bel);
407
457
if (iobb_loc.z != BelZ::IOBB_Z || iobb_loc.x != iob_loc.x || iobb_loc.y != iob_loc.y ) {
@@ -4108,6 +4158,9 @@ struct GowinPacker
4108
4158
pack_iobs ();
4109
4159
ctx->check ();
4110
4160
4161
+ pack_i3c ();
4162
+ ctx->check ();
4163
+
4111
4164
pack_mipi ();
4112
4165
ctx->check ();
4113
4166
0 commit comments