diff options
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | docs/format.html | 12 | ||||
-rw-r--r-- | icebox/icebox.py | 1 | ||||
-rw-r--r-- | iceprog/iceprog.c | 6 | ||||
-rw-r--r-- | icetime/icetime.cc | 53 |
5 files changed, 59 insertions, 15 deletions
@@ -1,7 +1,7 @@ Project IceStorm aims at documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. -See http://www.clifford.at/icestorm/ for more information. +See http://bygone.clairexen.net/icestorm/ for more information. Most of Project IceStorm is licensed under the ISC license: diff --git a/docs/format.html b/docs/format.html index 8d36151..ee7a655 100644 --- a/docs/format.html +++ b/docs/format.html @@ -47,8 +47,10 @@ The following commands are known: <table class="ctab"> <tr><th>Opcode</th><th>Description</th></tr> -<tr><td>0</td><td>payload=1: CRAM Data<br/> - payload=3: BRAM Data<br/> +<tr><td>0</td><td>payload=1: Write CRAM Data<br/> + payload=2: Read BRAM Data<br/> + payload=3: Write BRAM Data<br/> + payload=4: Read BRAM Data<br/> payload=5: Reset CRC<br/> payload=6: Wakeup<br/> payload=8: Reboot</td></tr> @@ -59,9 +61,9 @@ The following commands are known: payload=0: low<br/> payload=1: medium<br/> payload=2: high</td></tr> -<tr><td>6</td><td>Set bank width</td></tr> -<tr><td>7</td><td>Set bank height</td></tr> -<tr><td>8</td><td>Set bank offset</td></tr> +<tr><td>6</td><td>Set bank width (16-bits, MSB first)</td></tr> +<tr><td>7</td><td>Set bank height (16-bits, MSB first)</td></tr> +<tr><td>8</td><td>Set bank offset (16-bits, MSB first)</td></tr> <tr><td>9</td><td>payload=0: Disable warm boot<br/> payload=16: Enable cold boot<br/> payload=32: Enable warm boot</td></tr> diff --git a/icebox/icebox.py b/icebox/icebox.py index a7631a2..ef5478b 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -1719,7 +1719,6 @@ noplls_db = { "8k-cm81:4k": [ "8k_1" ], "1k-qn48": [ "1k" ], "1k-cb81": [ "1k" ], - "1k-cb121": [ "1k" ], "1k-vq100": [ "1k" ], "384-qn32": [ "384" ], } diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c index c671ac1..8ee6443 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c @@ -1008,7 +1008,7 @@ int main(int argc, char **argv) if (rc <= 0) break; fprintf(stderr, " \r"); - fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, addr / (file_size / 100)); + fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, 100 * addr / file_size); flash_write_enable(); flash_prog(rw_offset + addr, buffer, rc); flash_wait(); @@ -1030,7 +1030,7 @@ int main(int argc, char **argv) for (int addr = 0; addr < read_size; addr += 256) { uint8_t buffer[256]; fprintf(stderr, " \r"); - fprintf(stderr, "addr 0x%06X %3d%%\r", rw_offset + addr, addr / (read_size / 100)); + fprintf(stderr, "addr 0x%06X %3d%%\r", rw_offset + addr, 100 * addr / read_size); flash_read(rw_offset + addr, buffer, 256); fwrite(buffer, read_size - addr > 256 ? 256 : read_size - addr, 1, f); } @@ -1044,7 +1044,7 @@ int main(int argc, char **argv) if (rc <= 0) break; fprintf(stderr, " \r"); - fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, addr / (file_size / 100)); + fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, 100 * addr / file_size); flash_read(rw_offset + addr, buffer_flash, rc); if (memcmp(buffer_file, buffer_flash, rc)) { fprintf(stderr, "Found difference between flash and file!\n"); diff --git a/icetime/icetime.cc b/icetime/icetime.cc index d730fc6..fef65d2 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -59,6 +59,7 @@ std::set<std::tuple<int, int, int>> extra_bits; std::set<std::string> io_names; std::map<int, std::string> net_symbols; +std::map<std::string, unsigned> lc_lut_in_mask; bool get_config_bit(int tile_x, int tile_y, int bit_row, int bit_col) { @@ -221,10 +222,20 @@ void read_pcf(const char *filename) if (tok == nullptr || strcmp(tok, "set_io")) continue; + bool skip_next = false; std::vector<std::string> args; while ((tok = strtok(nullptr, " \t\r\n")) != nullptr) { + if(skip_next) { + skip_next = false; + continue; + } if (!strcmp(tok, "--warn-no-port")) continue; + if (!strcmp(tok, "-pullup") || !strcmp(tok, "-pullup_resistor")) { + skip_next = true; // skip argument + continue; + } + args.push_back(tok); } @@ -836,6 +847,15 @@ struct TimingAnalysis } if (driver_type == "LogicCell40" && (driver_port == "ltout" || driver_port == "lcout")) { + unsigned mask = lc_lut_in_mask.at(driver_cell); + if (inport == "in0" && ((mask & 0x1) == 0)) + continue; + if (inport == "in1" && ((mask & 0x2) == 0)) + continue; + if (inport == "in2" && ((mask & 0x4) == 0)) + continue; + if (inport == "in3" && ((mask & 0x8) == 0)) + continue; if (inport == "carryin") continue; } @@ -1221,14 +1241,37 @@ std::string make_lc40(int x, int y, int z) for (int i = 0; i < 20; i++) lcbits[i] = get_config_bit(x, y, lcbits_pos[i].first, lcbits_pos[i].second) ? '1' : '0'; + static const std::vector<int> lut_perm = { + 4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0, + }; + + unsigned lut_init = 0; + for (unsigned i = 0; i < lut_perm.size(); i++) + if (lcbits[lut_perm[i]] == '1') + lut_init |= (1U << i); + // FIXME: fill in the '0' netlist_cell_params[cell]["C_ON"] = stringf("1'b%c", lcbits[8]); netlist_cell_params[cell]["SEQ_MODE"] = stringf("4'b%c%c%c%c", lcbits[9], '0', '0', '0'); - netlist_cell_params[cell]["LUT_INIT"] = stringf("16'b%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", - lcbits[0], lcbits[10], lcbits[11], lcbits[1], - lcbits[2], lcbits[12], lcbits[13], lcbits[3], - lcbits[7], lcbits[17], lcbits[16], lcbits[6], - lcbits[5], lcbits[15], lcbits[14], lcbits[4]); + + std::string init = "16'b"; + for (int i = 15; i >= 0; i--) + init += ((lut_init >> i) & 0x1) ? '1' : '0'; + + netlist_cell_params[cell]["LUT_INIT"] = init; + + // Find which LUT inputs are "don't care" in the function, to avoid false paths for bits + // only affecting the carry. + lc_lut_in_mask[cell] = 0; + for (unsigned k = 0; k < 4; k++) { + for (unsigned i = 0; i < 16; i++) { + // If toggling the LUT input makes a difference it's not a don't care + if (((lut_init >> i) & 0x1U) != ((lut_init >> (i ^ (1U << k))) & 0x1U)) { + lc_lut_in_mask[cell] |= (1 << k); + break; + } + } + } if (lcbits[8] == '1') { |