diff options
author | David Shah <davey1576@gmail.com> | 2019-01-08 10:21:10 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-08 10:21:10 +0000 |
commit | c1d15c749c2aa105ee7b38ebe1b60a27e3743e8c (patch) | |
tree | b02d4869055c9790307dc89bfb69f06e88ca2995 /ice40 | |
parent | 747380537f5b5cd79305b54f60719f1c88c7478d (diff) | |
parent | 7d8b729ff4cd66e8dc7ce51dd7e2666f14d10cd7 (diff) | |
download | nextpnr-c1d15c749c2aa105ee7b38ebe1b60a27e3743e8c.tar.gz nextpnr-c1d15c749c2aa105ee7b38ebe1b60a27e3743e8c.tar.bz2 nextpnr-c1d15c749c2aa105ee7b38ebe1b60a27e3743e8c.zip |
Merge pull request #205 from YosysHQ/ice40_io_tmg
ice40: Add timing data for all IO modes
Diffstat (limited to 'ice40')
-rw-r--r-- | ice40/arch.cc | 68 | ||||
-rw-r--r-- | ice40/archdefs.h | 2 |
2 files changed, 67 insertions, 3 deletions
diff --git a/ice40/arch.cc b/ice40/arch.cc index 8f52987c..04c70e94 100644 --- a/ice40/arch.cc +++ b/ice40/arch.cc @@ -935,10 +935,34 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in return TMG_REGISTER_INPUT; } } else if (cell->type == id_SB_IO) { - if (port == id_D_IN_0 || port == id_D_IN_1) + if (port == id_INPUT_CLK || port == id_OUTPUT_CLK) + return TMG_CLOCK_INPUT; + if (port == id_CLOCK_ENABLE) { + clockInfoCount = 2; + return TMG_REGISTER_INPUT; + } + if ((port == id_D_IN_0 && !(cell->ioInfo.pintype & 0x1)) || port == id_D_IN_1) { + clockInfoCount = 1; + return TMG_REGISTER_OUTPUT; + } else if (port == id_D_IN_0) { return TMG_STARTPOINT; - if (port == id_D_OUT_0 || port == id_D_OUT_1 || port == id_OUTPUT_ENABLE) - return TMG_ENDPOINT; + } + if (port == id_D_OUT_0 || port == id_D_OUT_1) { + if ((cell->ioInfo.pintype & 0xC) == 0x8) { + return TMG_ENDPOINT; + } else { + clockInfoCount = 1; + return TMG_REGISTER_INPUT; + } + } + if (port == id_OUTPUT_ENABLE) { + if ((cell->ioInfo.pintype & 0x18) == 0x18) { + return TMG_REGISTER_INPUT; + } else { + return TMG_ENDPOINT; + } + } + return TMG_IGNORE; } else if (cell->type == id_ICESTORM_PLL) { if (port == id_PLLOUT_A || port == id_PLLOUT_B) @@ -998,6 +1022,41 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port info.setup.delay = 100; info.hold.delay = 0; } + } else if (cell->type == id_SB_IO) { + delay_t io_setup = 80, io_clktoq = 140; + if (args.type == ArchArgs::LP1K || args.type == ArchArgs::LP8K || args.type == ArchArgs::LP384) { + io_setup = 115; + io_clktoq = 210; + } else if (args.type == ArchArgs::UP5K) { + io_setup = 205; + io_clktoq = 1005; + } + if (port == id_CLOCK_ENABLE) { + info.clock_port = (index == 1) ? id_OUTPUT_CLK : id_INPUT_CLK; + info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE; + info.setup.delay = io_setup; + info.hold.delay = 0; + } else if (port == id_D_OUT_0 || port == id_OUTPUT_ENABLE) { + info.clock_port = id_OUTPUT_CLK; + info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE; + info.setup.delay = io_setup; + info.hold.delay = 0; + } else if (port == id_D_OUT_1) { + info.clock_port = id_OUTPUT_CLK; + info.edge = cell->ioInfo.negtrig ? RISING_EDGE : FALLING_EDGE; + info.setup.delay = io_setup; + info.hold.delay = 0; + } else if (port == id_D_IN_0) { + info.clock_port = id_INPUT_CLK; + info.edge = cell->ioInfo.negtrig ? FALLING_EDGE : RISING_EDGE; + info.clockToQ.delay = io_clktoq; + } else if (port == id_D_IN_1) { + info.clock_port = id_INPUT_CLK; + info.edge = cell->ioInfo.negtrig ? RISING_EDGE : FALLING_EDGE; + info.clockToQ.delay = io_clktoq; + } else { + NPNR_ASSERT_FALSE("no clock data for IO cell port"); + } } else if (cell->type == id_ICESTORM_DSP || cell->type == id_ICESTORM_SPRAM) { info.clock_port = cell->type == id_ICESTORM_SPRAM ? id_CLOCK : id_CLK; info.edge = RISING_EDGE; @@ -1065,6 +1124,9 @@ void Arch::assignCellInfo(CellInfo *cell) } else if (cell->type == id_SB_IO) { cell->ioInfo.lvds = str_or_default(cell->params, id_IO_STANDARD, "SB_LVCMOS") == "SB_LVDS_INPUT"; cell->ioInfo.global = bool_or_default(cell->attrs, this->id("GLOBAL")); + cell->ioInfo.pintype = int_or_default(cell->attrs, this->id("PIN_TYPE")); + cell->ioInfo.negtrig = bool_or_default(cell->attrs, this->id("NEG_TRIGGER")); + } else if (cell->type == id_SB_GB) { cell->gbInfo.forPadIn = bool_or_default(cell->attrs, this->id("FOR_PAD_IN")); } diff --git a/ice40/archdefs.h b/ice40/archdefs.h index 2bffe667..956fcb4c 100644 --- a/ice40/archdefs.h +++ b/ice40/archdefs.h @@ -151,6 +151,8 @@ struct ArchCellInfo { bool lvds; bool global; + bool negtrig; + int pintype; // TODO: clk packing checks... } ioInfo; struct |