diff --git a/ecp5/io.cc b/ecp5/io.cc new file mode 100644 index 00000000..e86c84f6 --- /dev/null +++ b/ecp5/io.cc @@ -0,0 +1,217 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * 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 "io.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_1V35: + return "1V35"; + 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 == "1V35") + return IOVoltage::VCC_1V35; + 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 ""; + 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: + return IOVoltage::VCC_3V3; + case IOType::LVCMOS25: + case IOType::LVCMOS25D: + case IOType::LVDS: + case IOType::SLVS: + case IOType::SUBLVDS: + case IOType::LVDS25E: + case IOType::MLVDS25: + case IOType::MLVDS25E: + case IOType::BLVDS25: + return IOVoltage::VCC_2V5; + case IOType::LVCMOS18: + case IOType::LVCMOS18D: + case IOType::SSTL18_I: + case IOType::SSTL18_II: + case IOType::SSTL18D_I: + case IOType::SSTL18D_II: + return IOVoltage::VCC_1V8; + case IOType::LVCMOS15: + case IOType::SSTL15_I: + case IOType::SSTL15_II: + case IOType::SSTL15D_I: + case IOType::SSTL15D_II: + return IOVoltage::VCC_1V5; + case IOType::SSTL135_I: + case IOType::SSTL135_II: + case IOType::SSTL135D_I: + case IOType::SSTL135D_II: + return IOVoltage::VCC_1V35; + case IOType::LVCMOS12: + case IOType::HSUL12: + case IOType::HSUL12D: + return IOVoltage::VCC_1V2; + default: + NPNR_ASSERT_FALSE("unknown IO type, unable to determine VccIO"); + } +} + +bool is_strong_vccio_constraint(IOType type, PortType dir, IOSide side) +{ + if (dir == PORT_OUT || dir == PORT_INOUT) + return true; + switch (type) { + case IOType::TYPE_NONE: + case IOType::LVCMOS33D: + case IOType::LVPECL33: + case IOType::LVDS: + case IOType::MLVDS25: + case IOType::BLVDS25: + case IOType::SLVS: + case IOType::SUBLVDS: + case IOType::LVCMOS12: + case IOType::HSUL12: + case IOType::HSUL12D: + return false; + case IOType::LVCMOS33: + case IOType::LVTTL33: + case IOType::LVCMOS25: + return (side == IOSide::LEFT || side == IOSide::RIGHT); + default: + return true; + } +} + +bool is_differential(IOType type) +{ + switch (type) { + case IOType::LVCMOS33D: + case IOType::LVCMOS25D: + case IOType::LVPECL33: + case IOType::LVDS: + case IOType::MLVDS25: + case IOType::BLVDS25: + case IOType::SLVS: + case IOType::SUBLVDS: + case IOType::LVCMOS18D: + case IOType::SSTL18D_I: + case IOType::SSTL18D_II: + case IOType::SSTL15D_I: + case IOType::SSTL15D_II: + case IOType::SSTL135D_I: + case IOType::SSTL135D_II: + case IOType::HSUL12D: + 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::SSTL15_I: + case IOType::SSTL15_II: + case IOType::SSTL15D_I: + case IOType::SSTL15D_II: + case IOType::SSTL135_I: + case IOType::SSTL135_II: + case IOType::SSTL135D_I: + case IOType::SSTL135D_II: + case IOType::HSUL12: + case IOType::HSUL12D: + return true; + default: + return false; + } +} + +bool valid_loc_for_io(IOType type, PortType dir, IOSide side, int z) +{ + bool is_lr = side == IOSide::LEFT || side == IOSide::RIGHT; + if (is_referenced(type) && !is_lr) + return false; + if (is_differential(type) && (!is_lr || ((z % 2) == 1))) + return false; + if ((type == IOType::LVCMOS18D || type == IOType::LVDS) && (dir == PORT_OUT || PORT_INOUT) && z != 0) + return false; + return true; +} + +NEXTPNR_NAMESPACE_END diff --git a/ecp5/io.h b/ecp5/io.h new file mode 100644 index 00000000..f0d941d9 --- /dev/null +++ b/ecp5/io.h @@ -0,0 +1,70 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 David Shah + * + * 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_1V35, + 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, +}; + +enum class IOSide +{ + LEFT, + RIGHT, + TOP, + BOTTOM, +}; + +std::string iotype_to_str(IOType type); +IOType ioType_from_str(const std::string &name); + +// IO related functions +IOVoltage get_vccio(IOType type); +bool is_strong_vccio_constraint(IOType type, PortType dir, IOSide side); +bool is_differential(IOType type); +bool is_referenced(IOType type); + +bool valid_loc_for_io(IOType type, PortType dir, IOSide side, int z); + +NEXTPNR_NAMESPACE_END + +#endif diff --git a/ecp5/iotypes.inc b/ecp5/iotypes.inc new file mode 100644 index 00000000..5984e79e --- /dev/null +++ b/ecp5/iotypes.inc @@ -0,0 +1,37 @@ +X(LVTTL33) +X(LVCMOS33) +X(LVCMOS25) +X(LVCMOS18) +X(LVCMOS15) +X(LVCMOS12) + +X(SSTL18_I) +X(SSTL18_II) +X(SSTL15_I) +X(SSTL15_II) +X(SSTL135_I) +X(SSTL135_II) +X(HSUL12) + +X(SSTL18D_I) +X(SSTL18D_II) +X(SSTL135D_I) +X(SSTL135D_II) +X(SSTL15D_I) +X(SSTL15D_II) +X(HSUL12D) +X(LVCMOS33D) +X(LVCMOS25D) + +X(LVDS) +X(BLVDS25) +X(MLVDS25) +X(LVPECL33) +X(SLVS) +X(SUBLVDS) +X(LVCMOS18D) + +X(LVDS25E) +X(BLVDS25E) +X(MLVDS25E) +X(LVPECL33E)