aboutsummaryrefslogtreecommitdiffstats
path: root/icebram
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2016-05-12 18:32:07 +0200
committerClifford Wolf <clifford@clifford.at>2016-05-12 18:32:07 +0200
commit2c553baeac92026177dcf3be95cb793f1a5c973d (patch)
tree3ab656702552922b7af3d50b25ea27b55dae5ab7 /icebram
parent0e1417249c832afabb3c81eb707d39efe94955df (diff)
downloadicestorm-2c553baeac92026177dcf3be95cb793f1a5c973d.tar.gz
icestorm-2c553baeac92026177dcf3be95cb793f1a5c973d.tar.bz2
icestorm-2c553baeac92026177dcf3be95cb793f1a5c973d.zip
Added icebram bitslice replacer
Diffstat (limited to 'icebram')
-rw-r--r--icebram/icebram.cc115
-rw-r--r--icebram/makedemo.py4
-rw-r--r--icebram/rundemo.sh2
3 files changed, 112 insertions, 9 deletions
diff --git a/icebram/icebram.cc b/icebram/icebram.cc
index a4cb415..cea30f5 100644
--- a/icebram/icebram.cc
+++ b/icebram/icebram.cc
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <assert.h>
#include <map>
#include <vector>
@@ -26,6 +27,7 @@
#include <iostream>
using std::map;
+using std::pair;
using std::vector;
using std::string;
using std::ifstream;
@@ -63,22 +65,24 @@ void help(const char *cmd)
printf("\n");
printf("Usage: %s [options] from_hexfile to_hexfile \n", cmd);
printf("\n");
- // printf(" -S\n");
- // printf(" Disable SIMPLE feedback path mode\n");
- // printf("\n");
+ printf(" -v\n");
+ printf(" verbose output\n");
+ printf("\n");
exit(1);
}
int main(int argc, char **argv)
{
+ bool verbose = false;
+
int opt;
- while ((opt = getopt(argc, argv, "")) != -1)
+ while ((opt = getopt(argc, argv, "v")) != -1)
{
switch (opt)
{
- // case 'i':
- // f_pllin = atof(optarg);
- // break;
+ case 'v':
+ verbose = true;
+ break;
default:
help(argv[0]);
}
@@ -87,6 +91,10 @@ int main(int argc, char **argv)
if (optind+2 != argc)
help(argv[0]);
+
+ // -------------------------------------------------------
+ // Load from_hexfile and to_hexfile
+
const char *from_hexfile_n = argv[optind];
ifstream from_hexfile_f(from_hexfile_n);
vector<vector<bool>> from_hexfile;
@@ -125,6 +133,50 @@ int main(int argc, char **argv)
exit(1);
}
+ if (from_hexfile.size() == 0 || from_hexfile.at(0).size() == 0) {
+ fprintf(stderr, "Empty from/to hexfiles!\n");
+ exit(1);
+ }
+
+ if (verbose)
+ fprintf(stderr, "Loaded pattern for %d bits wide and %d words deep memory.\n", int(from_hexfile.at(0).size()), int(from_hexfile.size()));
+
+
+ // -------------------------------------------------------
+ // Create bitslices from pattern data
+
+ map<vector<bool>, pair<vector<bool>, int>> pattern;
+
+ for (int i = 0; i < int(from_hexfile.at(0).size()); i++)
+ {
+ vector<bool> pattern_from, pattern_to;
+
+ for (int j = 0; j < int(from_hexfile.size()); j++)
+ {
+ pattern_from.push_back(from_hexfile.at(j).at(i));
+ pattern_to.push_back(to_hexfile.at(j).at(i));
+
+ if (pattern_from.size() == 256) {
+ if (pattern.count(pattern_from)) {
+ fprintf(stderr, "Conflicting from pattern for bit slice from_hexfile[%d:%d][%d]!\n", j, j-255, i);
+ exit(1);
+ }
+ pattern[pattern_from] = std::make_pair(pattern_to, 0);
+ pattern_from.clear(), pattern_to.clear();
+ }
+ }
+
+ assert(pattern_from.empty());
+ assert(pattern_to.empty());
+ }
+
+ if (verbose)
+ fprintf(stderr, "Extracted %d bit slices from from/to hexfile data.\n", int(pattern.size()));
+
+
+ // -------------------------------------------------------
+ // Read ascfile from stdin
+
vector<string> ascfile_lines;
map<string, vector<vector<bool>>> ascfile_hexdata;
@@ -145,7 +197,54 @@ int main(int argc, char **argv)
}
}
- // FIXME: Do the actual thing
+ if (verbose)
+ fprintf(stderr, "Found %d initialized bram cells in asc file.\n", int(ascfile_hexdata.size()));
+
+
+ // -------------------------------------------------------
+ // Replace bram data
+
+ int max_replace_cnt = 0;
+
+ for (auto &bram_it : ascfile_hexdata)
+ {
+ auto &bram_data = bram_it.second;
+
+ for (int i = 0; i < 16; i++)
+ {
+ vector<bool> from_bitslice;
+
+ for (int j = 0; j < 256; j++)
+ from_bitslice.push_back(bram_data.at(j / 16).at(16 * (j % 16) + i));
+
+ auto p = pattern.find(from_bitslice);
+ if (p != pattern.end())
+ {
+ auto &to_bitslice = p->second.first;
+
+ for (int j = 0; j < 256; j++)
+ bram_data.at(j / 16).at(16 * (j % 16) + i) = to_bitslice.at(j);
+
+ max_replace_cnt = std::max(++p->second.second, max_replace_cnt);
+ }
+ }
+ }
+
+ int min_replace_cnt = max_replace_cnt;
+ for (auto &it : pattern)
+ min_replace_cnt = std::min(min_replace_cnt, it.second.second);
+
+ if (min_replace_cnt != max_replace_cnt) {
+ fprintf(stderr, "Found some bitslices up to %d times, others only %d times!\n", max_replace_cnt, min_replace_cnt);
+ exit(1);
+ }
+
+ if (verbose)
+ fprintf(stderr, "Found and replaced %d instances of the memory.\n", max_replace_cnt);
+
+
+ // -------------------------------------------------------
+ // Write ascfile to stdout
for (size_t i = 0; i < ascfile_lines.size(); i++) {
auto &line = ascfile_lines.at(i);
diff --git a/icebram/makedemo.py b/icebram/makedemo.py
index bcec93f..35d3653 100644
--- a/icebram/makedemo.py
+++ b/icebram/makedemo.py
@@ -8,6 +8,10 @@ while True:
numrports = np.random.randint(1, 5)
if bram_width * bram_depth * numrports < 16*4096: break
+bram_width = 16
+bram_depth = 256
+numrports = 1
+
with open("demo.v", "wt") as f:
print("module demo (", file=f)
for i in range(numrports):
diff --git a/icebram/rundemo.sh b/icebram/rundemo.sh
index b2e7ecd..4e90ea2 100644
--- a/icebram/rundemo.sh
+++ b/icebram/rundemo.sh
@@ -5,7 +5,7 @@ python3 makedemo.py
yosys -p 'synth_ice40 -blif demo.blif' demo.v
arachne-pnr -d 8k -w demo.pcf -o demo.asc demo.blif
-./icebram demo_dat0.hex demo_dat1.hex < demo.asc > demo_new.asc
+./icebram -v demo_dat0.hex demo_dat1.hex < demo.asc > demo_new.asc
icebox_vlog -n demo -p demo.pcf -c demo_new.asc > demo_new.v
iverilog -o demo.vvp demo_tb.v demo_new.v $( yosys-config --datdir/ice40/cells_sim.v )