mirror of
https://github.com/YosysHQ/nextpnr.git
synced 2026-01-11 23:53:21 +00:00
MachXO2. Add support for several IO parameters. (#1572)
This commit is contained in:
parent
35810c9f87
commit
5194b5cc0a
@ -22,6 +22,8 @@ set(SOURCES
|
||||
globals.cc
|
||||
lpf.cc
|
||||
pack.cc
|
||||
pio.cc
|
||||
pio.h
|
||||
)
|
||||
|
||||
add_nextpnr_architecture(${family}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
#include "pio.h"
|
||||
|
||||
#define fmt_str(x) (static_cast<const std::ostringstream &>(std::ostringstream() << x).str())
|
||||
|
||||
@ -420,9 +421,45 @@ struct MachXO2Bitgen
|
||||
BelId bel = ci->bel;
|
||||
std::string pio = ctx->tile_info(bel)->bel_data[bel.index].name.get();
|
||||
std::string iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
|
||||
IOType io_type = ioType_from_str(iotype);
|
||||
std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
|
||||
std::string pic_tile = get_pic_tile(bel);
|
||||
cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);
|
||||
bool is_opendrain = false;
|
||||
|
||||
if (ci->attrs.count(id_OPENDRAIN)) {
|
||||
if (opendrain_capable(io_type, dir)) {
|
||||
cc.tiles[pic_tile].add_enum(pio + ".OPENDRAIN", str_or_default(ci->attrs, id_OPENDRAIN, "OFF"));
|
||||
is_opendrain = true;
|
||||
}
|
||||
else
|
||||
log_error("IO of type %s and direction %s cannot be set to opendrain\n", iotype.c_str(), dir.c_str());
|
||||
}
|
||||
|
||||
if (ci->attrs.count(id_SLEWRATE) && !is_differential(io_type) && dir != "INPUT")
|
||||
cc.tiles[pic_tile].add_enum(pio + ".SLEWRATE", str_or_default(ci->attrs, id_SLEWRATE, "SLOW"));
|
||||
if (ci->attrs.count(id_DIFFRESISTOR))
|
||||
cc.tiles[pic_tile].add_enum(pio + ".DIFFRESISTOR", str_or_default(ci->attrs, id_DIFFRESISTOR, "OFF"));
|
||||
|
||||
if (!is_opendrain) {
|
||||
if (ci->attrs.count(id_CLAMP))
|
||||
cc.tiles[pic_tile].add_enum(pio + ".CLAMP", str_or_default(ci->attrs, id_CLAMP, "OFF"));
|
||||
if (ci->attrs.count(id_PULLMODE) || dir == "INPUT")
|
||||
cc.tiles[pic_tile].add_enum(pio + ".PULLMODE", str_or_default(ci->attrs, id_PULLMODE, is_lvcmos(io_type) ? "DOWN" : "NONE"));
|
||||
}
|
||||
|
||||
if (ci->attrs.count(id_DRIVE) && !is_differential(io_type) && dir != "INPUT") {
|
||||
std::string drive = str_or_default(ci->attrs, id_DRIVE, "8");
|
||||
if (is_drive_ok(io_type, drive))
|
||||
cc.tiles[pic_tile].add_enum(pio + ".DRIVE", drive);
|
||||
else
|
||||
log_error("DRIVE %s cannot be set for IO type %s\n", drive.c_str(), iotype.c_str());
|
||||
}
|
||||
|
||||
if ((dir == "INPUT" || dir == "BIDIR") && !is_differential(ioType_from_str(iotype)) &&
|
||||
!is_referenced(ioType_from_str(iotype)) && ci->attrs.count(id_HYSTERESIS)) {
|
||||
cc.tiles[pic_tile].add_enum(pio + ".HYSTERESIS", str_or_default(ci->attrs, id_HYSTERESIS, "SMALL"));
|
||||
}
|
||||
}
|
||||
|
||||
void write_dcc(CellInfo *ci)
|
||||
|
||||
@ -24,6 +24,13 @@ X(PADDI)
|
||||
X(PADDO)
|
||||
X(PADDT)
|
||||
|
||||
X(CLAMP)
|
||||
X(DIFFRESISTOR)
|
||||
X(DRIVE)
|
||||
X(HYSTERESIS)
|
||||
X(OPENDRAIN)
|
||||
X(PULLMODE)
|
||||
|
||||
X(TRELLIS_SLICE)
|
||||
X(A0)
|
||||
X(B0)
|
||||
|
||||
41
machxo2/iotypes.inc
Normal file
41
machxo2/iotypes.inc
Normal file
@ -0,0 +1,41 @@
|
||||
X(LVTTL33)
|
||||
X(LVCMOS33)
|
||||
X(LVCMOS25)
|
||||
X(LVCMOS18)
|
||||
X(LVCMOS15)
|
||||
X(LVCMOS12)
|
||||
|
||||
X(SSTL25_I)
|
||||
X(SSTL25_II)
|
||||
X(SSTL18_I)
|
||||
X(SSTL18_II)
|
||||
X(HSTL18_I)
|
||||
X(HSTL18_II)
|
||||
|
||||
X(PCI33)
|
||||
|
||||
X(SSTL18D_I)
|
||||
X(SSTL18D_II)
|
||||
X(HSTL18D_I)
|
||||
X(HSTL18D_II)
|
||||
X(SSTL25D_I)
|
||||
X(SSTL25D_II)
|
||||
X(LVTTL33D)
|
||||
X(LVCMOS33D)
|
||||
X(LVCMOS25D)
|
||||
X(LVCMOS15D)
|
||||
X(LVCMOS12D)
|
||||
X(MIPI)
|
||||
|
||||
X(LVDS)
|
||||
X(BLVDS25)
|
||||
X(MLVDS25)
|
||||
X(LVPECL33)
|
||||
X(RSDS25)
|
||||
X(LVCMOS18D)
|
||||
|
||||
X(LVDS25E)
|
||||
X(BLVDS25E)
|
||||
X(MLVDS25E)
|
||||
X(LVPECL33E)
|
||||
|
||||
216
machxo2/pio.cc
Normal file
216
machxo2/pio.cc
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 gatecat <gatecat@ds0.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pio.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
std::string iovoltage_to_str(IOVoltage v)
|
||||
{
|
||||
switch (v) {
|
||||
case IOVoltage::VCC_3V3:
|
||||
return "3V3";
|
||||
case IOVoltage::VCC_2V5:
|
||||
return "2V5";
|
||||
case IOVoltage::VCC_1V8:
|
||||
return "1V8";
|
||||
case IOVoltage::VCC_1V5:
|
||||
return "1V5";
|
||||
case IOVoltage::VCC_1V2:
|
||||
return "1V2";
|
||||
}
|
||||
NPNR_ASSERT_FALSE("unknown IO voltage");
|
||||
}
|
||||
|
||||
IOVoltage iovoltage_from_str(const std::string &name)
|
||||
{
|
||||
if (name == "3V3")
|
||||
return IOVoltage::VCC_3V3;
|
||||
if (name == "2V5")
|
||||
return IOVoltage::VCC_2V5;
|
||||
if (name == "1V8")
|
||||
return IOVoltage::VCC_1V8;
|
||||
if (name == "1V5")
|
||||
return IOVoltage::VCC_1V5;
|
||||
if (name == "1V2")
|
||||
return IOVoltage::VCC_1V2;
|
||||
NPNR_ASSERT_FALSE("unknown IO voltage");
|
||||
}
|
||||
|
||||
std::string iotype_to_str(IOType type)
|
||||
{
|
||||
if (type == IOType::TYPE_NONE)
|
||||
return "NONE";
|
||||
#define X(t) \
|
||||
if (type == IOType::t) \
|
||||
return #t;
|
||||
#include "iotypes.inc"
|
||||
#undef X
|
||||
if (type == IOType::TYPE_UNKNOWN)
|
||||
return "<unknown>";
|
||||
NPNR_ASSERT_FALSE("unknown IO type");
|
||||
}
|
||||
|
||||
IOType ioType_from_str(const std::string &name)
|
||||
{
|
||||
if (name == "NONE")
|
||||
return IOType::TYPE_NONE;
|
||||
#define X(t) \
|
||||
if (name == #t) \
|
||||
return IOType::t;
|
||||
#include "iotypes.inc"
|
||||
return IOType::TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
IOVoltage get_vccio(IOType type)
|
||||
{
|
||||
switch (type) {
|
||||
case IOType::LVTTL33:
|
||||
case IOType::LVCMOS33:
|
||||
case IOType::LVCMOS33D:
|
||||
case IOType::LVPECL33:
|
||||
case IOType::LVPECL33E:
|
||||
case IOType::PCI33:
|
||||
return IOVoltage::VCC_3V3;
|
||||
case IOType::LVCMOS25:
|
||||
case IOType::LVCMOS25D:
|
||||
case IOType::LVDS:
|
||||
case IOType::RSDS25:
|
||||
case IOType::LVDS25E:
|
||||
case IOType::MLVDS25:
|
||||
case IOType::MLVDS25E:
|
||||
case IOType::BLVDS25:
|
||||
case IOType::SSTL25_I:
|
||||
case IOType::SSTL25_II:
|
||||
case IOType::SSTL25D_I:
|
||||
case IOType::SSTL25D_II:
|
||||
return IOVoltage::VCC_2V5;
|
||||
case IOType::LVCMOS18:
|
||||
case IOType::LVCMOS18D:
|
||||
case IOType::SSTL18_I:
|
||||
case IOType::SSTL18_II:
|
||||
case IOType::HSTL18_I:
|
||||
case IOType::HSTL18_II:
|
||||
case IOType::SSTL18D_I:
|
||||
case IOType::SSTL18D_II:
|
||||
case IOType::HSTL18D_I:
|
||||
case IOType::HSTL18D_II:
|
||||
return IOVoltage::VCC_1V8;
|
||||
case IOType::LVCMOS15:
|
||||
case IOType::LVCMOS15D:
|
||||
return IOVoltage::VCC_1V5;
|
||||
case IOType::LVCMOS12:
|
||||
case IOType::LVCMOS12D:
|
||||
case IOType::MIPI:
|
||||
return IOVoltage::VCC_1V2;
|
||||
default:
|
||||
NPNR_ASSERT_FALSE("unknown IO type, unable to determine VccIO");
|
||||
}
|
||||
}
|
||||
|
||||
bool is_differential(IOType type)
|
||||
{
|
||||
switch (type) {
|
||||
case IOType::LVCMOS33D:
|
||||
case IOType::LVCMOS25D:
|
||||
case IOType::LVCMOS15D:
|
||||
case IOType::LVCMOS12D:
|
||||
case IOType::LVPECL33:
|
||||
case IOType::LVDS:
|
||||
case IOType::MLVDS25:
|
||||
case IOType::BLVDS25:
|
||||
case IOType::LVCMOS18D:
|
||||
case IOType::SSTL18D_I:
|
||||
case IOType::SSTL18D_II:
|
||||
case IOType::SSTL25D_I:
|
||||
case IOType::SSTL25D_II:
|
||||
case IOType::HSTL18D_I:
|
||||
case IOType::HSTL18D_II:
|
||||
case IOType::MIPI:
|
||||
case IOType::RSDS25:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_referenced(IOType type)
|
||||
{
|
||||
switch (type) {
|
||||
case IOType::SSTL18_I:
|
||||
case IOType::SSTL18_II:
|
||||
case IOType::SSTL18D_I:
|
||||
case IOType::SSTL18D_II:
|
||||
case IOType::SSTL25_I:
|
||||
case IOType::SSTL25_II:
|
||||
case IOType::SSTL25D_I:
|
||||
case IOType::SSTL25D_II:
|
||||
case IOType::HSTL18_I:
|
||||
case IOType::HSTL18_II:
|
||||
case IOType::HSTL18D_I:
|
||||
case IOType::HSTL18D_II:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_lvcmos(IOType type)
|
||||
{
|
||||
switch (type) {
|
||||
case IOType::LVTTL33:
|
||||
case IOType::LVCMOS33:
|
||||
case IOType::LVCMOS25:
|
||||
case IOType::LVCMOS18:
|
||||
case IOType::LVCMOS15:
|
||||
case IOType::LVCMOS12:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_drive_ok(IOType type, std::string d)
|
||||
{
|
||||
switch (type) {
|
||||
case IOType::LVTTL33:
|
||||
case IOType::LVCMOS33:
|
||||
return (d == "4" || d == "8" || d == "12" || d == "16" || d == "24");
|
||||
case IOType::LVCMOS25:
|
||||
return (d == "4" || d == "8" || d == "12" || d == "16");
|
||||
case IOType::LVCMOS18:
|
||||
return (d == "4" || d == "8" || d == "12");
|
||||
case IOType::LVCMOS15:
|
||||
return (d == "4" || d == "8");
|
||||
case IOType::LVCMOS12:
|
||||
return (d == "2" || d == "6");
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool opendrain_capable(IOType type, std::string dir)
|
||||
{
|
||||
if (dir != "OUTPUT" && dir != "BIDIR")
|
||||
return false;
|
||||
|
||||
return is_lvcmos(type);
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
60
machxo2/pio.h
Normal file
60
machxo2/pio.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* nextpnr -- Next Generation Place and Route
|
||||
*
|
||||
* Copyright (C) 2018 gatecat <gatecat@ds0.me>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
#include "nextpnr.h"
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
enum class IOVoltage
|
||||
{
|
||||
VCC_3V3,
|
||||
VCC_2V5,
|
||||
VCC_1V8,
|
||||
VCC_1V5,
|
||||
VCC_1V2
|
||||
};
|
||||
|
||||
std::string iovoltage_to_str(IOVoltage v);
|
||||
IOVoltage iovoltage_from_str(const std::string &name);
|
||||
|
||||
enum class IOType
|
||||
{
|
||||
TYPE_NONE,
|
||||
#define X(t) t,
|
||||
#include "iotypes.inc"
|
||||
#undef X
|
||||
TYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
std::string iotype_to_str(IOType type);
|
||||
IOType ioType_from_str(const std::string &name);
|
||||
|
||||
// IO related functions
|
||||
bool is_differential(IOType type);
|
||||
bool is_referenced(IOType type);
|
||||
bool is_lvcmos(IOType type);
|
||||
bool is_drive_ok(IOType type, std::string d);
|
||||
bool opendrain_capable(IOType type, std::string dir);
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user