ice40: Add timing data for all IO modes
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
747380537f
commit
7d8b729ff4
@ -935,10 +935,34 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
|
|||||||
return TMG_REGISTER_INPUT;
|
return TMG_REGISTER_INPUT;
|
||||||
}
|
}
|
||||||
} else if (cell->type == id_SB_IO) {
|
} 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;
|
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;
|
return TMG_IGNORE;
|
||||||
} else if (cell->type == id_ICESTORM_PLL) {
|
} else if (cell->type == id_ICESTORM_PLL) {
|
||||||
if (port == id_PLLOUT_A || port == id_PLLOUT_B)
|
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.setup.delay = 100;
|
||||||
info.hold.delay = 0;
|
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) {
|
} 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.clock_port = cell->type == id_ICESTORM_SPRAM ? id_CLOCK : id_CLK;
|
||||||
info.edge = RISING_EDGE;
|
info.edge = RISING_EDGE;
|
||||||
@ -1065,6 +1124,9 @@ void Arch::assignCellInfo(CellInfo *cell)
|
|||||||
} else if (cell->type == id_SB_IO) {
|
} 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.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.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) {
|
} else if (cell->type == id_SB_GB) {
|
||||||
cell->gbInfo.forPadIn = bool_or_default(cell->attrs, this->id("FOR_PAD_IN"));
|
cell->gbInfo.forPadIn = bool_or_default(cell->attrs, this->id("FOR_PAD_IN"));
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,8 @@ struct ArchCellInfo
|
|||||||
{
|
{
|
||||||
bool lvds;
|
bool lvds;
|
||||||
bool global;
|
bool global;
|
||||||
|
bool negtrig;
|
||||||
|
int pintype;
|
||||||
// TODO: clk packing checks...
|
// TODO: clk packing checks...
|
||||||
} ioInfo;
|
} ioInfo;
|
||||||
struct
|
struct
|
||||||
|
Loading…
Reference in New Issue
Block a user