Skip to content

Commit b95a3ca

Browse files
yrabbitgatecat
authored andcommitted
Gowin. Implement MIPI IO.
Adds output (MIPI_OBUF and MIPI_OBUF_A) and input (MIPI_IBUF) primitives to allow the use of “real” MIPI (not emulation) ports capable of operating in both HS and LP modes. Signed-off-by: YRabbit <[email protected]>
1 parent cf9c745 commit b95a3ca

File tree

6 files changed

+245
-10
lines changed

6 files changed

+245
-10
lines changed

himbaechel/uarch/gowin/constids.inc

+10
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,16 @@ X(LSREN)
13131313
// EMCU
13141314
X(EMCU)
13151315

1316+
// MIPI
1317+
X(IL)
1318+
X(OH)
1319+
X(OL)
1320+
X(OENB)
1321+
X(MIPI_IBUF)
1322+
X(MIPI_OBUF)
1323+
X(MIPI_OBUF_A)
1324+
X(MODESEL)
1325+
13161326
// Register placement options
13171327
X(IREG_IN_IOB)
13181328
X(OREG_IN_IOB)

himbaechel/uarch/gowin/globals.cc

+16-3
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ struct GowinGlobalRouter
243243
bool driver_is_dqce(const PortRef &driver) { return CellTypePort(driver) == CellTypePort(id_DQCE, id_CLKOUT); }
244244
bool driver_is_dcs(const PortRef &driver) { return CellTypePort(driver) == CellTypePort(id_DCS, id_CLKOUT); }
245245
bool driver_is_dhcen(const PortRef &driver) { return CellTypePort(driver) == CellTypePort(id_DHCEN, id_CLKOUT); }
246+
bool driver_is_mipi(const PortRef &driver)
247+
{
248+
return CellTypePort(driver) == CellTypePort(id_IOBUF, id_O) && driver.cell->params.count(id_MIPI_IBUF);
249+
}
246250
bool driver_is_clksrc(const PortRef &driver)
247251
{
248252
// dedicated pins
@@ -506,7 +510,7 @@ struct GowinGlobalRouter
506510
NPNR_ASSERT(net_before_dhcen != nullptr);
507511

508512
PortRef driver = net_before_dhcen->driver;
509-
NPNR_ASSERT_MSG(driver_is_buf(driver) || driver_is_clksrc(driver),
513+
NPNR_ASSERT_MSG(driver_is_buf(driver) || driver_is_clksrc(driver) || driver_is_mipi(driver),
510514
stringf("The input source for %s is not a clock.", ctx->nameOf(dhcen_ci)).c_str());
511515

512516
IdString port;
@@ -519,8 +523,14 @@ struct GowinGlobalRouter
519523
WireId src = ctx->getBelPinWire(driver.cell->bel, port);
520524

521525
std::vector<PipId> path;
522-
RouteResult route_result = route_direct_net(
523-
net, [&](PipId pip, WireId src_wire) { return global_pip_filter(pip, src); }, src, &path);
526+
RouteResult route_result;
527+
if (driver_is_mipi(driver)) {
528+
route_result = route_direct_net(net, [&](PipId pip, WireId src_wire) { return true; }, src, &path);
529+
} else {
530+
route_result = route_direct_net(
531+
net, [&](PipId pip, WireId src_wire) { return global_pip_filter(pip, src); }, src, &path);
532+
}
533+
524534
if (route_result == NOT_ROUTED) {
525535
log_error("Can't route the %s network.\n", ctx->nameOf(net));
526536
}
@@ -557,6 +567,9 @@ struct GowinGlobalRouter
557567
hw_dhcen->setAttr(id_DHCEN_USED, 1);
558568
dhcen_ci->copyPortTo(id_CE, hw_dhcen, id_CE);
559569
}
570+
if (driver_is_mipi(driver)) {
571+
ctx->bindWire(src, net_before_dhcen, STRENGTH_LOCKED);
572+
}
560573

561574
// connect all users to upper level net
562575
std::vector<PortRef> users;

himbaechel/uarch/gowin/gowin.cc

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <regex>
21
#include <map>
2+
#include <regex>
33

44
#include "himbaechel_api.h"
55
#include "himbaechel_helpers.h"
@@ -110,7 +110,8 @@ struct GowinArch : HimbaechelArch
110110

111111
bool match_device(const std::string &device) override { return device.size() > 2 && device.substr(0, 2) == "GW"; }
112112

113-
std::unique_ptr<HimbaechelAPI> create(const std::string &device, const dict<std::string, std::string> &args) override
113+
std::unique_ptr<HimbaechelAPI> create(const std::string &device,
114+
const dict<std::string, std::string> &args) override
114115
{
115116
return std::make_unique<GowinImpl>();
116117
}
@@ -639,6 +640,9 @@ IdString GowinImpl::getBelBucketForCellType(IdString cell_type) const
639640
if (cell_type.in(id_IBUF, id_OBUF)) {
640641
return id_IOB;
641642
}
643+
if (cell_type.in(id_MIPI_OBUF, id_MIPI_OBUF_A)) {
644+
return id_MIPI_OBUF;
645+
}
642646
if (type_is_lut(cell_type)) {
643647
return id_LUT4;
644648
}
@@ -676,6 +680,9 @@ bool GowinImpl::isValidBelForCellType(IdString cell_type, BelId bel) const
676680
if (bel_type == id_IOB) {
677681
return cell_type.in(id_IBUF, id_OBUF);
678682
}
683+
if (bel_type == id_MIPI_OBUF) {
684+
return cell_type.in(id_MIPI_OBUF, id_MIPI_OBUF_A);
685+
}
679686
if (bel_type == id_LUT4) {
680687
return type_is_lut(cell_type);
681688
}

himbaechel/uarch/gowin/gowin.h

+7
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ inline bool type_is_diffio(IdString cell_type)
3232
}
3333
inline bool is_diffio(const CellInfo *cell) { return type_is_diffio(cell->type); }
3434

35+
// MIPI
36+
inline bool type_is_mipi(IdString cell_type) { return cell_type.in(id_MIPI_OBUF, id_MIPI_OBUF_A, id_MIPI_IBUF); }
37+
inline bool is_mipi(const CellInfo *cell) { return type_is_mipi(cell->type); }
38+
3539
// IOLOGIC input and output separately
3640

3741
inline bool type_is_iologico(IdString cell_type)
@@ -199,6 +203,9 @@ enum
199203

200204
EMCU_Z = 300,
201205

206+
MIPIOBUF_Z = 301,
207+
MIPIIBUF_Z = 302,
208+
202209
// The two least significant bits encode Z for 9-bit adders and
203210
// multipliers, if they are equal to 0, then we get Z of their common
204211
// 18-bit equivalent.

himbaechel/uarch/gowin/gowin_arch_gen.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@
5555

5656
USERFLASH_Z = 298
5757

58-
5958
EMCU_Z = 300
6059

60+
MIPIOBUF_Z = 301
61+
MIPIIBUF_Z = 302
62+
6163
DSP_Z = 509
6264

6365
DSP_0_Z = 511 # DSP macro 0
@@ -580,6 +582,23 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
580582
tt.add_bel_pin(bel, port, wire, PinType.OUTPUT)
581583
else:
582584
tt.add_bel_pin(bel, port, wire, PinType.INPUT)
585+
elif func == 'mipi_obuf':
586+
bel = tt.create_bel('MIPI_OBUF', 'MIPI_OBUF', MIPIOBUF_Z)
587+
elif func == 'mipi_ibuf':
588+
bel = tt.create_bel('MIPI_IBUF', 'MIPI_IBUF', MIPIIBUF_Z)
589+
wire = desc['HSREN']
590+
if not tt.has_wire(wire):
591+
tt.create_wire(wire)
592+
tt.add_bel_pin(bel, 'HSREN', wire, PinType.INPUT)
593+
wire = 'MIPIOL'
594+
if not tt.has_wire(wire):
595+
tt.create_wire(wire)
596+
tt.add_bel_pin(bel, 'OL', wire, PinType.OUTPUT)
597+
for i in range(2):
598+
wire = f'MIPIEN{i}'
599+
if not tt.has_wire(wire):
600+
tt.create_wire(wire)
601+
tt.add_bel_pin(bel, f'MIPIEN{i}', wire, PinType.INPUT)
583602
elif func == 'buf':
584603
for buf_type, wires in desc.items():
585604
for i, wire in enumerate(wires):

0 commit comments

Comments
 (0)