cyclonev: More validity checking thoughts
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
a6ea72fd84
commit
9eb0bc482e
@ -308,6 +308,19 @@ void Arch::add_bel_pin(BelId bel, IdString pin, PortType dir, WireId wire)
|
|||||||
wires[wire].bel_pins.push_back(bel_pin);
|
wires[wire].bel_pins.push_back(bel_pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Arch::assign_default_pinmap(CellInfo *cell)
|
||||||
|
{
|
||||||
|
for (auto &port : cell->ports) {
|
||||||
|
auto &pinmap = cell->pin_data[port.first].bel_pins;
|
||||||
|
if (!pinmap.empty())
|
||||||
|
continue; // already mapped
|
||||||
|
if (is_comb_cell(cell->type) && comb_pinmap.count(port.first))
|
||||||
|
pinmap.push_back(comb_pinmap.at(port.first)); // default comb mapping for placer purposes
|
||||||
|
else
|
||||||
|
pinmap.push_back(port.first); // default: assume bel pin named the same as cell pin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WITH_HEAP
|
#ifdef WITH_HEAP
|
||||||
const std::string Arch::defaultPlacer = "heap";
|
const std::string Arch::defaultPlacer = "heap";
|
||||||
#else
|
#else
|
||||||
|
@ -393,6 +393,11 @@ struct Arch : BaseArch<ArchRanges>
|
|||||||
|
|
||||||
BelInfo &bel_data(BelId bel) { return bels_by_tile.at(pos2idx(bel.pos)).at(bel.z); }
|
BelInfo &bel_data(BelId bel) { return bels_by_tile.at(pos2idx(bel.pos)).at(bel.z); }
|
||||||
const BelInfo &bel_data(BelId bel) const { return bels_by_tile.at(pos2idx(bel.pos)).at(bel.z); }
|
const BelInfo &bel_data(BelId bel) const { return bels_by_tile.at(pos2idx(bel.pos)).at(bel.z); }
|
||||||
|
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
void assign_default_pinmap(CellInfo *cell);
|
||||||
|
static const std::unordered_map<IdString, IdString> comb_pinmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
||||||
|
@ -124,10 +124,19 @@ struct ArchNetInfo
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum CellPinState
|
||||||
|
{
|
||||||
|
PIN_SIG = 0,
|
||||||
|
PIN_0 = 1,
|
||||||
|
PIN_1 = 2,
|
||||||
|
PIN_INV = 3,
|
||||||
|
};
|
||||||
|
|
||||||
struct ArchPinInfo
|
struct ArchPinInfo
|
||||||
{
|
{
|
||||||
// An inverter (INV) has been pushed onto this signal
|
// Used to represent signals that are either tied to implicit constants (rather than explicitly routed constants);
|
||||||
bool inverted;
|
// or are inverted
|
||||||
|
CellPinState state = PIN_SIG;
|
||||||
// The physical bel pins that this logical pin maps to
|
// The physical bel pins that this logical pin maps to
|
||||||
std::vector<IdString> bel_pins;
|
std::vector<IdString> bel_pins;
|
||||||
};
|
};
|
||||||
@ -167,6 +176,7 @@ struct ArchCellInfo
|
|||||||
const NetInfo *comb_out;
|
const NetInfo *comb_out;
|
||||||
|
|
||||||
int lut_input_count;
|
int lut_input_count;
|
||||||
|
int used_lut_input_count; // excluding those null/constant
|
||||||
int lut_bits_count;
|
int lut_bits_count;
|
||||||
|
|
||||||
bool is_carry, is_shared, is_extended;
|
bool is_carry, is_shared, is_extended;
|
||||||
|
@ -55,6 +55,7 @@ X(MISTRAL_ALUT4)
|
|||||||
X(MISTRAL_ALUT3)
|
X(MISTRAL_ALUT3)
|
||||||
X(MISTRAL_ALUT2)
|
X(MISTRAL_ALUT2)
|
||||||
X(MISTRAL_NOT)
|
X(MISTRAL_NOT)
|
||||||
|
X(MISTRAL_BUF)
|
||||||
X(MISTRAL_CONST)
|
X(MISTRAL_CONST)
|
||||||
X(MISTRAL_ALUT_ARITH)
|
X(MISTRAL_ALUT_ARITH)
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ ControlSig get_ctrlsig(const CellInfo *cell, IdString port)
|
|||||||
ControlSig result;
|
ControlSig result;
|
||||||
result.net = get_net_or_empty(cell, port);
|
result.net = get_net_or_empty(cell, port);
|
||||||
if (cell->pin_data.count(port))
|
if (cell->pin_data.count(port))
|
||||||
result.inverted = cell->pin_data.at(port).inverted;
|
result.inverted = cell->pin_data.at(port).state == PIN_INV;
|
||||||
else
|
else
|
||||||
result.inverted = false;
|
result.inverted = false;
|
||||||
return result;
|
return result;
|
||||||
@ -259,7 +259,8 @@ void Arch::assign_comb_info(CellInfo *cell) const
|
|||||||
++cell->combInfo.lut_input_count;
|
++cell->combInfo.lut_input_count;
|
||||||
cell->combInfo.lut_in[1] = get_net_or_empty(cell, id_B);
|
cell->combInfo.lut_in[1] = get_net_or_empty(cell, id_B);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case ID_MISTRAL_NOT:
|
case ID_MISTRAL_BUF: // used to route through to FFs etc
|
||||||
|
case ID_MISTRAL_NOT: // used for inverters that map to LUTs
|
||||||
++cell->combInfo.lut_input_count;
|
++cell->combInfo.lut_input_count;
|
||||||
cell->combInfo.lut_in[0] = get_net_or_empty(cell, id_A);
|
cell->combInfo.lut_in[0] = get_net_or_empty(cell, id_A);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
@ -272,6 +273,10 @@ void Arch::assign_comb_info(CellInfo *cell) const
|
|||||||
// Note that this relationship won't hold for extended mode, when that is supported
|
// Note that this relationship won't hold for extended mode, when that is supported
|
||||||
cell->combInfo.lut_bits_count = (1 << cell->combInfo.lut_input_count);
|
cell->combInfo.lut_bits_count = (1 << cell->combInfo.lut_input_count);
|
||||||
}
|
}
|
||||||
|
cell->combInfo.used_lut_input_count = 0;
|
||||||
|
for (int i = 0; i < cell->combInfo.lut_input_count; i++)
|
||||||
|
if (cell->combInfo.lut_in[i])
|
||||||
|
++cell->combInfo.used_lut_input_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Arch::assign_ff_info(CellInfo *cell) const
|
void Arch::assign_ff_info(CellInfo *cell) const
|
||||||
@ -336,9 +341,9 @@ bool Arch::is_alm_legal(uint32_t lab, uint8_t alm) const
|
|||||||
// There are two ways to route from the fabric into FF data - either routing through a LUT or using the E/F
|
// There are two ways to route from the fabric into FF data - either routing through a LUT or using the E/F
|
||||||
// signals and SLOAD=1 (*PKREF*)
|
// signals and SLOAD=1 (*PKREF*)
|
||||||
bool route_thru_lut_avail = !luts[i] && (total_lut_inputs < 8) && (used_lut_bits < 64);
|
bool route_thru_lut_avail = !luts[i] && (total_lut_inputs < 8) && (used_lut_bits < 64);
|
||||||
// E/F is available if the LUT is using less than 6 inputs - TODO: is this correct considering all possible LUT
|
// E/F is available if this LUT is using 3 or fewer inputs - this is conservative and sharing can probably
|
||||||
// sharing
|
// improve this situation
|
||||||
bool ef_available = (!luts[i] || luts[i]->combInfo.lut_input_count < 6);
|
bool ef_available = (!luts[i] || luts[i]->combInfo.used_lut_input_count <= 3);
|
||||||
// Control set checking
|
// Control set checking
|
||||||
bool found_ff = false;
|
bool found_ff = false;
|
||||||
|
|
||||||
@ -383,4 +388,12 @@ bool Arch::is_lab_ctrlset_legal(uint32_t lab) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This default cell-bel pin mapping is used to provide estimates during placement only. It will have errors and
|
||||||
|
// overlaps and a correct mapping will be resolved twixt placement and routing
|
||||||
|
const std::unordered_map<IdString, IdString> Arch::comb_pinmap = {
|
||||||
|
{id_A, id_F0}, // fastest input first
|
||||||
|
{id_B, id_E0}, {id_C, id_D}, {id_D, id_C}, {id_D0, id_C}, {id_D1, id_B},
|
||||||
|
{id_E, id_B}, {id_F, id_A}, {id_Q, id_COMBOUT}, {id_SO, id_COMBOUT},
|
||||||
|
};
|
||||||
|
|
||||||
NEXTPNR_NAMESPACE_END
|
NEXTPNR_NAMESPACE_END
|
Loading…
Reference in New Issue
Block a user