Merge pull request #2133 from dh73/nodev_head
[yosys.git] / techlibs / ice40 / ice40_braminit.cc
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <bitset>
25
26 USING_YOSYS_NAMESPACE
27 PRIVATE_NAMESPACE_BEGIN
28
29 static void run_ice40_braminit(Module *module)
30 {
31 for (auto cell : module->selected_cells())
32 {
33 uint16_t mem[256];
34
35 /* Only consider cells we're interested in */
36 if (cell->type != ID(SB_RAM40_4K) &&
37 cell->type != ID(SB_RAM40_4KNR) &&
38 cell->type != ID(SB_RAM40_4KNW) &&
39 cell->type != ID(SB_RAM40_4KNRNW))
40 continue;
41 if (!cell->hasParam(ID(INIT_FILE)))
42 continue;
43 std::string init_file = cell->getParam(ID(INIT_FILE)).decode_string();
44 cell->unsetParam(ID(INIT_FILE));
45 if (init_file == "")
46 continue;
47
48 /* Open file */
49 log("Processing %s : %s\n", RTLIL::id2cstr(cell->name), init_file.c_str());
50
51 std::ifstream f;
52 f.open(init_file.c_str());
53 if (f.fail()) {
54 log("Can not open file `%s`.\n", init_file.c_str());
55 continue;
56 }
57
58 /* Defaults to 0 */
59 memset(mem, 0x00, sizeof(mem));
60
61 /* Process each line */
62 bool in_comment = false;
63 int cursor = 0;
64
65 while (!f.eof())
66 {
67 std::string line, token;
68 std::getline(f, line);
69
70 for (int i = 0; i < GetSize(line); i++)
71 {
72 if (in_comment && line.compare(i, 2, "*/") == 0) {
73 line[i] = ' ';
74 line[i+1] = ' ';
75 in_comment = false;
76 continue;
77 }
78 if (!in_comment && line.compare(i, 2, "/*") == 0)
79 in_comment = true;
80 if (in_comment)
81 line[i] = ' ';
82 }
83
84 while (1)
85 {
86 bool set_cursor = false;
87 long value;
88
89 token = next_token(line, " \t\r\n");
90 if (token.empty() || token.compare(0, 2, "//") == 0)
91 break;
92
93 if (token[0] == '@') {
94 token = token.substr(1);
95 set_cursor = true;
96 }
97
98 const char *nptr = token.c_str();
99 char *endptr;
100 value = strtol(nptr, &endptr, 16);
101 if (!*nptr || *endptr) {
102 log("Can not parse %s `%s` for %s.\n",
103 set_cursor ? "address" : "value",
104 nptr, token.c_str()
105 );
106 continue;
107 }
108
109 if (set_cursor)
110 cursor = value;
111 else if (cursor >= 0 && cursor < 256)
112 mem[cursor++] = value;
113 else
114 log("Attempt to initialize non existent address %d\n", cursor);
115 }
116 }
117
118 /* Set attributes */
119 const char *hex = "0123456789ABCDEF";
120 for (int i=0; i<16; i++) {
121 std::string val = "";
122 for (int j=15; j>=0; j--)
123 val += std::bitset<16>(mem[i*16+j]).to_string();
124 cell->setParam("\\INIT_" + std::string(1, hex[i]), RTLIL::Const::from_string(val));
125 }
126 }
127 }
128
129 struct Ice40BRAMInitPass : public Pass {
130 Ice40BRAMInitPass() : Pass("ice40_braminit", "iCE40: perform SB_RAM40_4K initialization from file") { }
131 void help() override
132 {
133 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
134 log("\n");
135 log(" ice40_braminit\n");
136 log("\n");
137 log("This command processes all SB_RAM40_4K blocks with a non-empty INIT_FILE\n");
138 log("parameter and converts it into the required INIT_x attributes\n");
139 log("\n");
140 }
141 void execute(std::vector<std::string> args, RTLIL::Design *design) override
142 {
143 log_header(design, "Executing ICE40_BRAMINIT pass.\n");
144
145 size_t argidx;
146 for (argidx = 1; argidx < args.size(); argidx++) {
147 // if (args[argidx] == "-???") {
148 // continue;
149 // }
150 break;
151 }
152 extra_args(args, argidx, design);
153
154 for (auto module : design->selected_modules())
155 run_ice40_braminit(module);
156 }
157 } Ice40BRAMInitPass;
158
159 PRIVATE_NAMESPACE_END