aboutsummaryrefslogtreecommitdiffstats
path: root/ice40
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-10 13:24:48 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-10 13:24:48 +0200
commit30e672313dc1dd1223b1641583ea509417ae9b61 (patch)
tree809b11dcd8709dfad82f4142e02f4531840703d6 /ice40
parentd0bd657551e449aa14a3fcc04401cbd9efb9fb96 (diff)
downloadnextpnr-30e672313dc1dd1223b1641583ea509417ae9b61.tar.gz
nextpnr-30e672313dc1dd1223b1641583ea509417ae9b61.tar.bz2
nextpnr-30e672313dc1dd1223b1641583ea509417ae9b61.zip
ice40: Add IO config to bitstream
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'ice40')
-rw-r--r--ice40/bitstream.cc76
-rw-r--r--ice40/chip.h15
-rw-r--r--ice40/chipdb.py19
3 files changed, 93 insertions, 17 deletions
diff --git a/ice40/bitstream.cc b/ice40/bitstream.cc
index 6ed6279d..524a8fee 100644
--- a/ice40/bitstream.cc
+++ b/ice40/bitstream.cc
@@ -25,7 +25,9 @@ inline TileType tile_at(const Chip &chip, int x, int y)
return chip.chip_info.tile_grid[y * chip.chip_info.width + x];
}
-const ConfigEntryPOD &find_config(const TileInfoPOD &tile, const std::string &name) {
+const ConfigEntryPOD &find_config(const TileInfoPOD &tile,
+ const std::string &name)
+{
for (int i = 0; i < tile.num_config_entries; i++) {
if (std::string(tile.entries[i].name) == name) {
return tile.entries[i];
@@ -34,7 +36,22 @@ const ConfigEntryPOD &find_config(const TileInfoPOD &tile, const std::string &na
assert(false);
}
-void set_config(const TileInfoPOD &ti, vector<vector<int8_t>> &tile_cfg, const std::string &name, bool value, int index = -1) {
+std::tuple<int8_t, int8_t, int8_t> get_ieren(const BitstreamInfoPOD &bi,
+ int8_t x, int8_t y, int8_t z)
+{
+ for (int i = 0; i < bi.num_ierens; i++) {
+ auto ie = bi.ierens[i];
+ if (ie.iox == x && ie.ioy == y && ie.ioz == z) {
+ return std::make_tuple(ie.ierx, ie.iery, ie.ierz);
+ }
+ }
+ // No pin at this location
+ return std::make_tuple(-1, -1, -1);
+};
+
+void set_config(const TileInfoPOD &ti, vector<vector<int8_t>> &tile_cfg,
+ const std::string &name, bool value, int index = -1)
+{
const ConfigEntryPOD &cfg = find_config(ti, name);
if (index == -1) {
for (int i = 0; i < cfg.num_bits; i++) {
@@ -90,8 +107,12 @@ void write_asc(const Design &design, std::ostream &out)
const PipInfoPOD &pi = ci.pip_data[pip.index];
const SwitchInfoPOD &swi = bi.switches[pi.switch_index];
for (int i = 0; i < swi.num_bits; i++) {
- bool val = (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
- int8_t &cbit = config.at(swi.y).at(swi.x).at(swi.cbits[i].row).at(swi.cbits[i].col);
+ bool val =
+ (pi.switch_mask & (1 << ((swi.num_bits - 1) - i))) != 0;
+ int8_t &cbit = config.at(swi.y)
+ .at(swi.x)
+ .at(swi.cbits[i].row)
+ .at(swi.cbits[i].col);
if (bool(cbit) != 0)
assert(false);
cbit = val;
@@ -101,13 +122,15 @@ void write_asc(const Design &design, std::ostream &out)
// Set logic cell config
for (auto cell : design.cells) {
BelId bel = cell.second->bel;
- if (bel == BelId())
- std::cout << "Found unplaced cell " << cell.first << " while generating bitstream!" << std::endl;
+ if (bel == BelId()) {
+ std::cout << "Found unplaced cell " << cell.first
+ << " while generating bitstream!" << std::endl;
+ continue;
+ }
+ const BelInfoPOD &beli = ci.bel_data[bel.index];
+ int x = beli.x, y = beli.y, z = beli.z;
if (cell.second->type == "ICESTORM_LC") {
- const BelInfoPOD &beli = ci.bel_data[bel.index];
- int x = beli.x, y = beli.y, z = beli.z;
TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
-
unsigned lut_init = std::stoi(cell.second->params["LUT_INIT"]);
bool neg_clk = std::stoi(cell.second->params["NEG_CLK"]);
bool dff_enable = std::stoi(cell.second->params["DFF_ENABLE"]);
@@ -129,15 +152,44 @@ void write_asc(const Design &design, std::ostream &out)
lc.at(19) = async_sr;
for (int i = 0; i < 20; i++)
- set_config(ti, config.at(y).at(x), "LC_" + std::to_string(z), lc.at(i), i);
+ set_config(ti, config.at(y).at(x), "LC_" + std::to_string(z),
+ lc.at(i), i);
set_config(ti, config.at(y).at(x), "NegClk", neg_clk);
} else if (cell.second->type == "SB_IO") {
- // TODO
+ TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
+ unsigned pin_type = std::stoi(cell.second->params["PIN_TYPE"]);
+ bool neg_trigger = std::stoi(cell.second->params["NEG_TRIGGER"]);
+ bool pullup = std::stoi(cell.second->params["PULLUP"]);
+ for (int i = 0; i < 6; i++) {
+ bool val = (pin_type >> i) & 0x01;
+ set_config(ti, config.at(y).at(x),
+ "IOB_" + std::to_string(z) + ".PINTYPE_" +
+ std::to_string(i),
+ val);
+ }
+
+ auto ieren = get_ieren(bi, x, y, z);
+ int iex, iey, iez;
+ std::tie(iex, iey, iez) = ieren;
+ assert(iez != -1);
+
+ bool input_en = false;
+ if ((chip.wire_to_net[chip.getWireBelPin(bel, PIN_D_IN_0).index] !=
+ IdString()) ||
+ (chip.wire_to_net[chip.getWireBelPin(bel, PIN_D_IN_1).index] !=
+ IdString())) {
+ input_en = true;
+ }
+ set_config(ti, config.at(iey).at(iex),
+ "IoCtrl.IE_" + std::to_string(iez), !input_en);
+ set_config(ti, config.at(iey).at(iex),
+ "IoCtrl.REN_" + std::to_string(iez), !pullup);
} else {
assert(false);
}
}
- // Set other config bits - currently just disable RAM to stop icebox_vlog crashing
+ // Set other config bits - currently just disable RAM to stop icebox_vlog
+ // crashing
// TODO: ColBufCtrl , unused IO
for (int y = 0; y < ci.height; y++) {
for (int x = 0; x < ci.width; x++) {
diff --git a/ice40/chip.h b/ice40/chip.h
index 1a978fcd..84b2196a 100644
--- a/ice40/chip.h
+++ b/ice40/chip.h
@@ -144,11 +144,18 @@ struct SwitchInfoPOD
ConfigBitPOD cbits[max_switch_bits];
};
+struct IerenInfoPOD
+{
+ int8_t iox, ioy, ioz;
+ int8_t ierx, iery, ierz;
+};
+
struct BitstreamInfoPOD
{
- int num_switches;
+ int num_switches, num_ierens;
TileInfoPOD *tiles_nonrouting;
SwitchInfoPOD *switches;
+ IerenInfoPOD *ierens;
};
struct ChipInfoPOD
@@ -563,7 +570,8 @@ struct Chip
pip_to_net[pip.index] = net;
// Optimise?
for (int i = 0; i < chip_info.num_pips; i++) {
- if (chip_info.pip_data[i].switch_index == chip_info.pip_data[pip.index].switch_index)
+ if (chip_info.pip_data[i].switch_index ==
+ chip_info.pip_data[pip.index].switch_index)
pips_locked[i] = true;
}
}
@@ -575,7 +583,8 @@ struct Chip
pip_to_net[pip.index] = IdString();
// Optimise?
for (int i = 0; i < chip_info.num_pips; i++) {
- if (chip_info.pip_data[i].switch_index == chip_info.pip_data[pip.index].switch_index)
+ if (chip_info.pip_data[i].switch_index ==
+ chip_info.pip_data[pip.index].switch_index)
pips_locked[i] = false;
}
}
diff --git a/ice40/chipdb.py b/ice40/chipdb.py
index a543298c..a92704eb 100644
--- a/ice40/chipdb.py
+++ b/ice40/chipdb.py
@@ -21,6 +21,8 @@ bel_wires = list()
switches = list()
+ierens = list()
+
wire_uphill_belport = dict()
wire_downhill_belports = dict()
@@ -117,6 +119,10 @@ with open(sys.argv[1], "r") as f:
tile_sizes[4] = (int(line[1]), int(line[2]))
continue
+ if line[0] == ".ieren":
+ mode = ("ieren",)
+ continue
+
if (line[0][0] == ".") or (mode is None):
mode = None
continue
@@ -173,6 +179,8 @@ with open(sys.argv[1], "r") as f:
bits.append((int(m.group(1)), int(m.group(2))))
tile_bits[mode[1]].append((name, bits))
+ if mode[0] == "ieren":
+ ierens.append(tuple([int(_) for _ in line]))
def add_bel_input(bel, wire, port):
if wire not in wire_downhill_belports:
wire_downhill_belports[wire] = set()
@@ -409,7 +417,9 @@ for switch in switches:
switchinfo.append("{%d, %d, %d, {%s}}" % (x, y, len(bits), cbits))
switchid += 1
-
+iereninfo = []
+for ieren in ierens:
+ iereninfo.append("{%d, %d, %d, %d, %d, %d}" % ieren)
print("static WireInfoPOD wire_data_%s[%d] = {" % (dev_name, num_wires))
print(",\n".join(wireinfo))
@@ -427,8 +437,13 @@ print("static TileInfoPOD tile_data_%s[%d] = {" % (dev_name, num_tile_types))
print(",\n".join(tileinfo))
print("};")
+print("static IerenInfoPOD ieren_data_%s[%d] = {" % (dev_name, len(iereninfo)))
+print(",\n".join(iereninfo))
+print("};")
+
+
print("static BitstreamInfoPOD bits_info_%s = {" % dev_name)
-print("%d, tile_data_%s, switch_data_%s" % (len(switchinfo), dev_name, dev_name))
+print("%d, %d, tile_data_%s, switch_data_%s, ieren_data_%s" % (len(switchinfo), len(iereninfo), dev_name, dev_name, dev_name))
print("};")
print("static TileType tile_grid_%s[%d] = {" % (dev_name, len(tilegrid)))