Skip to content

Commit

Permalink
Gowin. Implement MIPI IO.
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
yrabbit committed Jan 23, 2025
1 parent 1623243 commit 1708999
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 10 deletions.
10 changes: 10 additions & 0 deletions himbaechel/uarch/gowin/constids.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1313,6 +1313,16 @@ X(LSREN)
// EMCU
X(EMCU)

// MIPI
X(IL)
X(OH)
X(OL)
X(OENB)
X(MIPI_IBUF)
X(MIPI_OBUF)
X(MIPI_OBUF_A)
X(MODESEL)

// Register placement options
X(IREG_IN_IOB)
X(OREG_IN_IOB)
Expand Down
19 changes: 16 additions & 3 deletions himbaechel/uarch/gowin/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ struct GowinGlobalRouter
bool driver_is_dqce(const PortRef &driver) { return CellTypePort(driver) == CellTypePort(id_DQCE, id_CLKOUT); }
bool driver_is_dcs(const PortRef &driver) { return CellTypePort(driver) == CellTypePort(id_DCS, id_CLKOUT); }
bool driver_is_dhcen(const PortRef &driver) { return CellTypePort(driver) == CellTypePort(id_DHCEN, id_CLKOUT); }
bool driver_is_mipi(const PortRef &driver)
{
return CellTypePort(driver) == CellTypePort(id_IOBUF, id_O) && driver.cell->params.count(id_MIPI_IBUF);
}
bool driver_is_clksrc(const PortRef &driver)
{
// dedicated pins
Expand Down Expand Up @@ -506,7 +510,7 @@ struct GowinGlobalRouter
NPNR_ASSERT(net_before_dhcen != nullptr);

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

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

std::vector<PipId> path;
RouteResult route_result = route_direct_net(
net, [&](PipId pip, WireId src_wire) { return global_pip_filter(pip, src); }, src, &path);
RouteResult route_result;
if (driver_is_mipi(driver)) {
route_result = route_direct_net(net, [&](PipId pip, WireId src_wire) { return true; }, src, &path);
} else {
route_result = route_direct_net(
net, [&](PipId pip, WireId src_wire) { return global_pip_filter(pip, src); }, src, &path);
}

if (route_result == NOT_ROUTED) {
log_error("Can't route the %s network.\n", ctx->nameOf(net));
}
Expand Down Expand Up @@ -557,6 +567,9 @@ struct GowinGlobalRouter
hw_dhcen->setAttr(id_DHCEN_USED, 1);
dhcen_ci->copyPortTo(id_CE, hw_dhcen, id_CE);
}
if (driver_is_mipi(driver)) {
ctx->bindWire(src, net_before_dhcen, STRENGTH_LOCKED);
}

// connect all users to upper level net
std::vector<PortRef> users;
Expand Down
11 changes: 9 additions & 2 deletions himbaechel/uarch/gowin/gowin.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <regex>
#include <map>
#include <regex>

#include "himbaechel_api.h"
#include "himbaechel_helpers.h"
Expand Down Expand Up @@ -110,7 +110,8 @@ struct GowinArch : HimbaechelArch

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

std::unique_ptr<HimbaechelAPI> create(const std::string &device, const dict<std::string, std::string> &args) override
std::unique_ptr<HimbaechelAPI> create(const std::string &device,
const dict<std::string, std::string> &args) override
{
return std::make_unique<GowinImpl>();
}
Expand Down Expand Up @@ -639,6 +640,9 @@ IdString GowinImpl::getBelBucketForCellType(IdString cell_type) const
if (cell_type.in(id_IBUF, id_OBUF)) {
return id_IOB;
}
if (cell_type.in(id_MIPI_OBUF, id_MIPI_OBUF_A)) {
return id_MIPI_OBUF;
}
if (type_is_lut(cell_type)) {
return id_LUT4;
}
Expand Down Expand Up @@ -676,6 +680,9 @@ bool GowinImpl::isValidBelForCellType(IdString cell_type, BelId bel) const
if (bel_type == id_IOB) {
return cell_type.in(id_IBUF, id_OBUF);
}
if (bel_type == id_MIPI_OBUF) {
return cell_type.in(id_MIPI_OBUF, id_MIPI_OBUF_A);
}
if (bel_type == id_LUT4) {
return type_is_lut(cell_type);
}
Expand Down
7 changes: 7 additions & 0 deletions himbaechel/uarch/gowin/gowin.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ inline bool type_is_diffio(IdString cell_type)
}
inline bool is_diffio(const CellInfo *cell) { return type_is_diffio(cell->type); }

// MIPI
inline bool type_is_mipi(IdString cell_type) { return cell_type.in(id_MIPI_OBUF, id_MIPI_OBUF_A, id_MIPI_IBUF); }
inline bool is_mipi(const CellInfo *cell) { return type_is_mipi(cell->type); }

// IOLOGIC input and output separately

inline bool type_is_iologico(IdString cell_type)
Expand Down Expand Up @@ -199,6 +203,9 @@ enum

EMCU_Z = 300,

MIPIOBUF_Z = 301,
MIPIIBUF_Z = 302,

// 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
21 changes: 20 additions & 1 deletion himbaechel/uarch/gowin/gowin_arch_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@

USERFLASH_Z = 298


EMCU_Z = 300

MIPIOBUF_Z = 301
MIPIIBUF_Z = 302

DSP_Z = 509

DSP_0_Z = 511 # DSP macro 0
Expand Down Expand Up @@ -580,6 +582,23 @@ def create_extra_funcs(tt: TileType, db: chipdb, x: int, y: int):
tt.add_bel_pin(bel, port, wire, PinType.OUTPUT)
else:
tt.add_bel_pin(bel, port, wire, PinType.INPUT)
elif func == 'mipi_obuf':
bel = tt.create_bel('MIPI_OBUF', 'MIPI_OBUF', MIPIOBUF_Z)
elif func == 'mipi_ibuf':
bel = tt.create_bel('MIPI_IBUF', 'MIPI_IBUF', MIPIIBUF_Z)
wire = desc['HSREN']
if not tt.has_wire(wire):
tt.create_wire(wire)
tt.add_bel_pin(bel, 'HSREN', wire, PinType.INPUT)
wire = 'MIPIOL'
if not tt.has_wire(wire):
tt.create_wire(wire)
tt.add_bel_pin(bel, 'OL', wire, PinType.OUTPUT)
for i in range(2):
wire = f'MIPIEN{i}'
if not tt.has_wire(wire):
tt.create_wire(wire)
tt.add_bel_pin(bel, f'MIPIEN{i}', wire, PinType.INPUT)
elif func == 'buf':
for buf_type, wires in desc.items():
for i, wire in enumerate(wires):
Expand Down
Loading

0 comments on commit 1708999

Please sign in to comment.