aboutsummaryrefslogtreecommitdiffstats
path: root/bba
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2018-07-24 21:10:42 +0200
committerClifford Wolf <clifford@clifford.at>2018-07-24 21:10:42 +0200
commitc3859072d4e621186e7b4ded3d2311ce0e8d31ba (patch)
tree118c1fe5df54a31cf516a3ca4fe72aa6e5940095 /bba
parent1b7b4ece06645c5d98b009b9a53e368817163c4b (diff)
downloadnextpnr-c3859072d4e621186e7b4ded3d2311ce0e8d31ba.tar.gz
nextpnr-c3859072d4e621186e7b4ded3d2311ce0e8d31ba.tar.bz2
nextpnr-c3859072d4e621186e7b4ded3d2311ce0e8d31ba.zip
Use bbasm to create iCE40 chipdb
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'bba')
-rw-r--r--bba/main.cc206
1 files changed, 194 insertions, 12 deletions
diff --git a/bba/main.cc b/bba/main.cc
index 3ef4c1ca..53c70b83 100644
--- a/bba/main.cc
+++ b/bba/main.cc
@@ -3,8 +3,10 @@
#include <string>
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <assert.h>
+#include <unistd.h>
enum TokenType : int8_t
{
@@ -35,18 +37,48 @@ std::vector<std::string> preText, postText;
const char *skipWhitespace(const char *p)
{
+ if (p == nullptr)
+ return "";
while (*p == ' ' || *p == '\t')
p++;
return p;
}
-int main()
+int main(int argc, char **argv)
{
- bool verbose = true;
- // bool bigEndian = false;
+ bool verbose = false;
+ bool bigEndian = false;
+ bool writeC = false;
char buffer[512];
- while (fgets(buffer, 512, stdin) != nullptr)
+ int opt;
+ while ((opt = getopt(argc, argv, "vbc")) != -1)
+ {
+ switch (opt)
+ {
+ case 'v':
+ verbose = true;
+ break;
+ case 'b':
+ bigEndian = true;
+ break;
+ case 'c':
+ writeC = true;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ assert(optind+2 == argc);
+
+ FILE *fileIn = fopen(argv[optind], "rt");
+ assert(fileIn != nullptr);
+
+ FILE *fileOut = fopen(argv[optind+1], writeC ? "wt" : "wb");
+ assert(fileOut != nullptr);
+
+ while (fgets(buffer, 512, fileIn) != nullptr)
{
std::string cmd = strtok(buffer, " \t\r\n");
@@ -63,7 +95,7 @@ int main()
}
if (cmd == "push") {
- const char *p = strtok(buffer, " \t\r\n");
+ const char *p = strtok(nullptr, " \t\r\n");
if (streamIndex.count(p) == 0) {
streamIndex[p] = streams.size();
streams.resize(streams.size() + 1);
@@ -79,8 +111,8 @@ int main()
}
if (cmd == "label" || cmd == "ref") {
- const char *label = strtok(buffer, " \t\r\n");
- const char *comment = skipWhitespace(strtok(buffer, "\r\n"));
+ const char *label = strtok(nullptr, " \t\r\n");
+ const char *comment = skipWhitespace(strtok(nullptr, "\r\n"));
Stream &s = streams.at(streamStack.back());
if (labelIndex.count(label) == 0) {
labelIndex[label] = labels.size();
@@ -94,8 +126,8 @@ int main()
}
if (cmd == "u8" || cmd == "u16" || cmd == "u32") {
- const char *value = strtok(buffer, " \t\r\n");
- const char *comment = skipWhitespace(strtok(buffer, "\r\n"));
+ const char *value = strtok(nullptr, " \t\r\n");
+ const char *comment = skipWhitespace(strtok(nullptr, "\r\n"));
Stream &s = streams.at(streamStack.back());
s.tokenTypes.push_back(cmd == "u8" ? TOK_U8 : cmd == "u16" ? TOK_U16 : TOK_U32);
s.tokenValues.push_back(atoll(value));
@@ -104,8 +136,8 @@ int main()
continue;
}
- if (cmd == "s") {
- const char *value = skipWhitespace(strtok(buffer, "\r\n"));
+ if (cmd == "str") {
+ const char *value = skipWhitespace(strtok(nullptr, "\r\n"));
std::string label = std::string("str:") + value;
Stream &s = streams.at(streamStack.back());
if (labelIndex.count(label) == 0) {
@@ -128,7 +160,13 @@ int main()
continue;
}
- abort();
+ assert(0);
+ }
+
+ if (verbose) {
+ printf("Constructed %d streams:\n", int(streams.size()));
+ for (auto &s : streams)
+ printf(" stream '%s' with %d tokens\n", s.name.c_str(), int(s.tokenTypes.size()));
}
assert(!streams.empty());
@@ -137,5 +175,149 @@ int main()
streams.back().tokenTypes.swap(stringStream.tokenTypes);
streams.back().tokenValues.swap(stringStream.tokenValues);
+ int cursor = 0;
+ for (auto &s : streams) {
+ for (int i = 0; i < int(s.tokenTypes.size()); i++) {
+ switch (s.tokenTypes[i])
+ {
+ case TOK_LABEL:
+ labels[s.tokenValues[i]] = cursor;
+ break;
+ case TOK_REF:
+ cursor += 4;
+ break;
+ case TOK_U8:
+ cursor += 1;
+ break;
+ case TOK_U16:
+ assert(cursor % 2 == 0);
+ cursor += 2;
+ break;
+ case TOK_U32:
+ assert(cursor % 4 == 0);
+ cursor += 4;
+ break;
+ default:
+ assert(0);
+ }
+ }
+ }
+
+ if (verbose) {
+ printf("resolved positions for %d labels.\n", int(labels.size()));
+ printf("total data (including strings): %.2f MB\n", double(cursor) / (1024*1024));
+ }
+
+ std::vector<uint8_t> data(cursor);
+
+ cursor = 0;
+ for (auto &s : streams) {
+ for (int i = 0; i < int(s.tokenTypes.size()); i++) {
+ uint32_t value = s.tokenValues[i];
+ int numBytes = 0;
+
+ switch (s.tokenTypes[i])
+ {
+ case TOK_LABEL:
+ break;
+ case TOK_REF:
+ value = labels[value] - cursor;
+ numBytes = 4;
+ break;
+ case TOK_U8:
+ numBytes = 1;
+ break;
+ case TOK_U16:
+ numBytes = 2;
+ break;
+ case TOK_U32:
+ numBytes = 4;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (bigEndian) {
+ switch (numBytes)
+ {
+ case 4:
+ data[cursor++] = value >> 24;
+ data[cursor++] = value >> 16;
+ /* fall-through */
+ case 2:
+ data[cursor++] = value >> 8;
+ /* fall-through */
+ case 1:
+ data[cursor++] = value;
+ /* fall-through */
+ case 0:
+ break;
+ default:
+ assert(0);
+ }
+ } else {
+ switch (numBytes)
+ {
+ case 4:
+ data[cursor+3] = value >> 24;
+ data[cursor+2] = value >> 16;
+ /* fall-through */
+ case 2:
+ data[cursor+1] = value >> 8;
+ /* fall-through */
+ case 1:
+ data[cursor] = value;
+ /* fall-through */
+ case 0:
+ break;
+ default:
+ assert(0);
+ }
+ cursor += numBytes;
+ }
+ }
+ }
+
+ assert(cursor == int(data.size()));
+
+ if (writeC) {
+ for (auto &s : preText)
+ fprintf(fileOut, "%s\n", s.c_str());
+
+ fprintf(fileOut, "const char %s[%d] =\n\"", streams[0].name.c_str(), int(data.size())+1);
+
+ cursor = 1;
+ for (auto d : data) {
+ if (cursor > 70) {
+ fputc('\"', fileOut);
+ fputc('\n', fileOut);
+ cursor = 0;
+ }
+ if (cursor == 0) {
+ fputc('\"', fileOut);
+ cursor = 1;
+ }
+ if (d < 32 || d >= 128) {
+ fprintf(fileOut, "\\%03o", int(d));
+ cursor += 4;
+ } else
+ if (d == '\"' || d == '\'' || d == '\\') {
+ fputc('\\', fileOut);
+ fputc(d, fileOut);
+ cursor += 2;
+ } else {
+ fputc(d, fileOut);
+ cursor++;
+ }
+ }
+
+ fprintf(fileOut, "\";\n");
+
+ for (auto &s : postText)
+ fprintf(fileOut, "%s\n", s.c_str());
+ } else {
+ fwrite(data.data(), int(data.size()), 1, fileOut);
+ }
+
return 0;
}