galaxians
[fpga-games] / galaxian / romgen / romgen.cpp
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string>
4 #include <math.h>
5 #include <iostream>
6 using namespace std;
7
8 #define MAX_ROM_SIZE 0x4000
9
10 int main(int argc, char* argv[])
11
12 {
13 cerr << "romgen by MikeJ version 3.00\n";
14 // read file
15
16 string buffer;
17 FILE *fin;
18
19 if(argc < 5)
20 {
21 cerr << "\nUsage: romgen <input file> <entity name> <number of address bits>\n";
22 cerr << " <format> {registered} {enable}\n";
23 cerr << "\n";
24 cerr << "Now uses bit_vector generics for compatibilty with Xilinx UniSim library\n";
25 cerr << "\n";
26 cerr << "for the format paramater use :\n";
27 cerr << " a - rtl model rom array \n";
28 cerr << " c - rtl model case statement \n";
29 cerr << " b - Xilinx block ram4 (registered output always)\n";
30 cerr << " l - Xilinx block ram16 (registered output always)\n";
31 cerr << " d - Xilinx distributed ram [not supported yet]\n";
32 cerr << "\n";
33 cerr << "for the registered paramater (optional) use :\n";
34 cerr << " r - registered output (combinatorial otherwise) \n";
35 cerr << "\n";
36 cerr << "for the enable paramater (optional) use :\n";
37 cerr << " e - clock enable generated \n";
38 cerr << "\n";
39 cerr << "note, generated roms are always 8 bits wide\n";
40 cerr << " max 12 address bits for block ram4s\n";
41 cerr << " max 14 address bits for block ram16s\n";
42 cerr << "for example romgen fred.bin fred_rom 12 c r\n\n";
43 return -1;
44 }
45
46 fin = fopen(argv[1],"rb");
47 if (fin == NULL) {
48 cerr << "ERROR : Could not open input file " << argv[1] <<"\n";
49 return -1;
50 }
51
52 char rom_type = 0;
53 char option_1 = 0;
54 char option_2 = 0;
55 sscanf(argv[4],"%c",&rom_type);
56 if (argc > 5) sscanf(argv[5],"%c",&option_1);
57 if (argc > 6) sscanf(argv[6],"%c",&option_2);
58
59 bool format_case = false;
60 bool format_array = false;
61 bool format_block = false;
62 bool format_dist = false;
63 bool format_clock = false;
64 bool format_ram16 = false;
65 bool format_ena = false;
66
67 cerr << "INFO : creating entity : " << argv[2] << "\n";
68
69 if (option_1 != 0) {
70 if ((option_1 == 'r') || (option_1 == 'R'))
71 format_clock = true;
72 else if ((option_1 == 'e') || (option_1 == 'E'))
73 format_ena = true;
74 else {
75 cerr << "ERROR : output option not supported\n";
76 return -1;
77 }
78 }
79
80 // lazy ...
81 if (option_2 != 0) {
82 if ((option_2 == 'r') || (option_2 == 'R'))
83 format_clock = true;
84 else if ((option_2 == 'e') || (option_2 == 'E'))
85 format_ena = true;
86 else {
87 cerr << "ERROR : output option not supported\n";
88 return -1;
89 }
90 }
91
92 if ((rom_type == 'c') || (rom_type == 'C')) {
93 cerr << "INFO : rtl model, case statement \n"; format_case = true; }
94 else if ((rom_type == 'a') || (rom_type == 'A')) {
95 cerr << "INFO : rtl model, rom array \n"; format_array = true; }
96 else if ((rom_type == 'b') || (rom_type == 'B')) {
97 cerr << "INFO : block4 ram, registered \n"; format_block = true; format_clock = true; }
98 else if ((rom_type == 'l') || (rom_type == 'L')) {
99 cerr << "INFO : block16 ram, registered \n"; format_block = true; format_clock = true; format_ram16 = true; }
100 //else if ((rom_type == 'd') || (rom_type == 'D')) {
101 // cerr << "INFO : distributed ram, combinatorial; \n"; format_dist = true; }
102 else {
103 cerr << "ERROR : format not supported\n";
104 return -1;
105 }
106 if (format_clock == true)
107 cerr << "INFO : registered output\n\n";
108 else
109 cerr << "INFO : combinatorial output\n\n";
110
111
112 // calc number of address bits required
113 int addr_bits;
114 int max_addr_bits = 16;
115 int rom_inits = 16;
116
117 if (format_block == true) {
118 if (format_ram16 == true) {
119 max_addr_bits = 14;
120 rom_inits = 64;
121 }
122 else
123 max_addr_bits = 12;
124 }
125
126 sscanf(argv[3],"%d",&addr_bits);
127 if (addr_bits < 1 || addr_bits > max_addr_bits) {
128 cerr << "ERROR : illegal rom size, number of address bits must be between 1 and " << max_addr_bits << "\n";
129 return -1;
130 }
131 // ram b16s
132 // for 14 bits use ram_b16_s1 x data_width
133 // for 13 bits use ram_b16_s2 x data_width/2
134 // for 12 bits use ram_b16_s4 x data_width/4
135 // for<=11 bits use ram_b16_s8 x data_width/8
136
137 // ram b4s
138 // for 12 bits use ram_b4_s1 x data_width
139 // for 11 bits use ram_b4_s2 x data_width/2
140 // for 10 bits use ram_b4_s4 x data_width/4
141 // for <=9 bits use ram_b4_s8 x data_width/8
142 int rom_size = (int) pow(2,addr_bits);
143
144 int number_of_block_rams = 1;
145 int block_ram_width = 8;
146 int block_ram_pwidth = 0;
147 int block_ram_abits = 9;
148
149 if (format_ram16 == true) {
150 block_ram_abits = 11; // default
151 block_ram_pwidth = 1;
152 // ram16s
153 switch (addr_bits) {
154 case 14 : number_of_block_rams = 8; block_ram_width = 1; block_ram_pwidth = 0; block_ram_abits = 14; break;
155 case 13 : number_of_block_rams = 4; block_ram_width = 2; block_ram_pwidth = 0; block_ram_abits = 13; break;
156 case 12 : number_of_block_rams = 2; block_ram_width = 4; block_ram_pwidth = 0; block_ram_abits = 12; break;
157 default : ;
158 }
159 }
160 else {
161 // ram4s
162 switch (addr_bits) {
163 case 12 : number_of_block_rams = 8; block_ram_width = 1; block_ram_abits = 12; break;
164 case 11 : number_of_block_rams = 4; block_ram_width = 2; block_ram_abits = 11; break;
165 case 10 : number_of_block_rams = 2; block_ram_width = 4; block_ram_abits = 10; break;
166 default : ;
167 }
168 }
169
170 //printf("block ram w : %d ",block_ram_width);
171 //printf("block ram n : %d ",number_of_block_rams);
172
173
174 // process
175 int mem[MAX_ROM_SIZE];
176 string line;
177
178 int i,j,k;
179
180
181 int addr = 0;
182 int offset = 0;
183 int mask = 0;
184 unsigned int data = 0;
185
186 // clear mem
187 for (i = 0; i < MAX_ROM_SIZE; i++) mem[i] = 0;
188
189 // process file
190 data = getc(fin);
191 while (!feof(fin) && (addr < rom_size)) {
192 if (addr >= MAX_ROM_SIZE) {
193 cerr << "ERROR : file too large\n";
194 return -1;
195 }
196
197 mem[addr] = data;
198 // debug
199 //if (addr % 16 == 0) printf("%04x : ",addr);
200 //printf("%02x ",data);
201 //if (addr % 16 == 15) printf("\n");
202 // end debug
203 addr ++;
204 data = getc(fin);
205 }
206 fclose(fin);
207
208
209 printf("-- generated with romgen v3.0 by MikeJ\n");
210 printf("library ieee;\n");
211 printf(" use ieee.std_logic_1164.all;\n");
212 printf(" use ieee.std_logic_unsigned.all;\n");
213 printf(" use ieee.numeric_std.all;\n");
214 printf("\n");
215 printf("library UNISIM;\n");
216 printf(" use UNISIM.Vcomponents.all;\n");
217 printf("\n");
218 printf("entity %s is\n",argv[2]);
219 printf(" port (\n");
220 if (format_clock == true) printf(" CLK : in std_logic;\n");
221 if (format_ena == true) printf(" ENA : in std_logic;\n");
222 printf(" ADDR : in std_logic_vector(%d downto 0);\n",addr_bits - 1);
223 printf(" DATA : out std_logic_vector(7 downto 0)\n");
224 printf(" );\n");
225 printf("end;\n");
226 printf("\n");
227 printf("architecture RTL of %s is\n",argv[2]);
228 printf("\n");
229
230 // if blockram
231 //{{{
232 if (format_block == true) {
233 printf(" function romgen_str2bv (str : string) return bit_vector is\n");
234 printf(" variable result : bit_vector (str'length*4-1 downto 0);\n");
235 printf(" begin\n");
236 printf(" for i in 0 to str'length-1 loop\n");
237 printf(" case str(str'high-i) is\n");
238 for (i = 0; i<16; i++)
239 printf(" when '%01X' => result(i*4+3 downto i*4) := x\042%01X\042;\n",i,i);
240 printf(" when others => null;\n");
241 printf(" end case;\n");
242 printf(" end loop;\n");
243 printf(" return result;\n");
244 printf(" end romgen_str2bv;\n");
245 printf("\n");
246
247 // xilinx block ram component
248 if (block_ram_pwidth != 0) {
249 for (i = 0; i< 8; i++)
250 printf(" attribute INITP_%02X : string;\n",i);
251 printf("\n");
252 }
253
254 for (i = 0; i< rom_inits; i++)
255 printf(" attribute INIT_%02X : string;\n",i);
256 printf("\n");
257
258 if (format_ram16 == true)
259 printf(" component RAMB16_S%d\n",block_ram_width + block_ram_pwidth);
260 else
261 printf(" component RAMB4_S%d\n",block_ram_width);
262
263 printf(" --pragma translate_off\n");
264 printf(" generic (\n");
265 if (block_ram_pwidth != 0) {
266 for (i = 0; i< 8; i++) {
267 printf(" INITP_%02X : bit_vector (255 downto 0) := x\0420000000000000000000000000000000000000000000000000000000000000000\042",i);
268 printf(";\n");
269 }
270 printf("\n");
271 }
272
273 for (i = 0; i< rom_inits; i++) {
274 printf(" INIT_%02X : bit_vector (255 downto 0) := x\0420000000000000000000000000000000000000000000000000000000000000000\042",i);
275 if (i< (rom_inits - 1)) printf(";");
276 printf("\n");
277 }
278 printf(" );\n");
279 printf(" --pragma translate_on\n");
280 printf(" port (\n");
281 printf(" DO : out std_logic_vector (%d downto 0);\n",block_ram_width -1);
282 if (block_ram_pwidth != 0)
283 printf(" DOP : out std_logic_vector (%d downto 0);\n",block_ram_pwidth -1);
284 printf(" ADDR : in std_logic_vector (%d downto 0);\n",block_ram_abits -1);
285 printf(" CLK : in std_logic;\n");
286 printf(" DI : in std_logic_vector (%d downto 0);\n",block_ram_width -1);
287 if (block_ram_pwidth != 0)
288 printf(" DIP : in std_logic_vector (%d downto 0);\n",block_ram_pwidth -1);
289 printf(" EN : in std_logic;\n");
290 if (format_ram16 == true)
291 printf(" SSR : in std_logic;\n");
292 else
293 printf(" RST : in std_logic;\n");
294 printf(" WE : in std_logic \n");
295 printf(" );\n");
296 printf(" end component;\n");
297 printf("\n");
298 printf(" signal rom_addr : std_logic_vector(%d downto 0);\n",block_ram_abits - 1);
299 printf("\n");
300 }
301 //}}}
302 //{{{
303 if (format_array == true) {
304 printf("\n");
305 printf(" type ROM_ARRAY is array(0 to %d) of std_logic_vector(7 downto 0);\n",rom_size - 1);
306 printf(" constant ROM : ROM_ARRAY := (\n");
307 for (i = 0; i < rom_size; i ++ ) {
308 if (i % 8 == 0) printf(" ");
309 printf("x\042%02X\042",mem[i]);
310 if (i < (rom_size - 1)) printf(",");
311 if (i == (rom_size - 1)) printf(" ");
312 if (i % 8 == 7) printf(" -- 0x%04X\n",i - 7);
313 }
314 printf(" );\n");
315 printf("\n");
316 } // end array
317 //}}}
318 //{{{
319 if (format_case == true) {
320 printf(" signal rom_addr : std_logic_vector(11 downto 0);\n");
321 printf("\n");
322 }
323 //}}}
324
325 printf("begin\n");
326 printf("\n");
327 //
328 if ((format_block == true) || (format_case == true)) {
329 printf(" p_addr : process(ADDR)\n");
330 printf(" begin\n");
331 printf(" rom_addr <= (others => '0');\n");
332 printf(" rom_addr(%d downto 0) <= ADDR;\n",addr_bits - 1);
333 printf(" end process;\n");
334 printf("\n");
335 }
336 //
337 //{{{
338 if (format_block == true) {
339 for (k = 0; k < number_of_block_rams; k ++){
340 printf(" rom%d : if true generate\n",k);
341
342 for (j = 0; j < rom_inits; j++) {
343 printf(" attribute INIT_%02X of inst : label is \042",j);
344 switch (block_ram_width) {
345
346 case 1 : // width 1
347 mask = 0x1 << (k);
348 for (i = 0; i < 256; i+=8) {
349 data = ((mem[(j*256) + (255 - i)] & mask) >> k);
350 data <<= 1;
351 data += ((mem[(j*256) + (254 - i)] & mask) >> k);
352 data <<= 1;
353 data += ((mem[(j*256) + (253 - i)] & mask) >> k);
354 data <<= 1;
355 data += ((mem[(j*256) + (252 - i)] & mask) >> k);
356 data <<= 1;
357 data += ((mem[(j*256) + (251 - i)] & mask) >> k);
358 data <<= 1;
359 data += ((mem[(j*256) + (250 - i)] & mask) >> k);
360 data <<= 1;
361 data += ((mem[(j*256) + (249 - i)] & mask) >> k);
362 data <<= 1;
363 data += ((mem[(j*256) + (248 - i)] & mask) >> k);
364 printf("%02X",data);
365 }
366 break;
367
368 case 2 : // width 2
369 mask = 0x3 << (k * 2);
370 for (i = 0; i < 128; i+=4) {
371 data = ((mem[(j*128) + (127 - i)] & mask) >> k * 2);
372 data <<= 2;
373 data += ((mem[(j*128) + (126 - i)] & mask) >> k * 2);
374 data <<= 2;
375 data += ((mem[(j*128) + (125 - i)] & mask) >> k * 2);
376 data <<= 2;
377 data += ((mem[(j*128) + (124 - i)] & mask) >> k * 2);
378 printf("%02X",data);
379 }
380 break;
381
382 case 4 : // width 4
383 mask = 0xF << (k * 4);
384 for (i = 0; i < 64; i+=2) {
385 data = ((mem[(j*64) + (63 - i)] & mask) >> k * 4);
386 data <<= 4;
387 data += ((mem[(j*64) + (62 - i)] & mask) >> k * 4);
388
389 printf("%02X",data);
390 }
391 break;
392
393
394 case 8 : // width 8
395 for (i = 0; i < 32; i++) {
396 data = ((mem[(j*32) + (31 - i)]));
397 printf("%02X",data);
398 }
399 break;
400 } // end switch
401
402 printf("\042;\n");
403 }
404
405 printf(" begin\n");
406 if (format_ram16 == true)
407 printf(" inst : RAMB16_S%d\n",block_ram_width + block_ram_pwidth);
408 else
409 printf(" inst : RAMB4_S%d\n",block_ram_width);
410
411 printf(" --pragma translate_off\n");
412 printf(" generic map (\n");
413
414 if (block_ram_pwidth != 0) {
415 for (i = 0; i< 8; i++) {
416 printf(" INITP_%02X => x\0420000000000000000000000000000000000000000000000000000000000000000\042",i);
417 printf(",\n");
418 }
419 printf("\n");
420 }
421
422 for (i = 0; i< rom_inits; i++) {
423 printf(" INIT_%02X => romgen_str2bv(inst'INIT_%02X)",i,i);
424 if (i< (rom_inits - 1)) printf(",");
425 printf("\n");
426 }
427 printf(" )\n");
428 printf(" --pragma translate_on\n");
429 printf(" port map (\n");
430 printf(" DO => DATA(%d downto %d),\n",((k+1) * block_ram_width)-1,k*block_ram_width);
431 if (block_ram_pwidth != 0)
432 printf(" DOP => open,\n");
433 printf(" ADDR => rom_addr,\n");
434 printf(" CLK => CLK,\n");
435 printf(" DI => \042");
436 for (i = 0; i < block_ram_width -1; i++) printf("0");
437 printf("0\042,\n");
438 if (block_ram_pwidth != 0) {
439 printf(" DIP => \042");
440 for (i = 0; i < block_ram_pwidth -1; i++) printf("0");
441 printf("0\042,\n");
442 }
443 if (format_ena == true)
444 printf(" EN => ENA,\n");
445 else
446 printf(" EN => '1',\n");
447 //
448 if (format_ram16 == true)
449 printf(" SSR => '0',\n");
450 else
451 printf(" RST => '0',\n");
452 printf(" WE => '0'\n");
453 printf(" );\n");
454 printf(" end generate;\n");
455 }
456 } // end block ram
457 //}}}
458
459 //{{{
460 if (format_array == true) {
461 if (format_clock == true)
462 printf(" p_rom : process\n");
463 else
464 printf(" p_rom : process(ADDR)\n");
465 printf(" begin\n");
466 if (format_clock == true)
467 printf(" wait until rising_edge(CLK);\n");
468 if (format_ena == true)
469 printf(" if (ENA = '1') then\n ");
470 printf(" DATA <= ROM(to_integer(unsigned(ADDR)));\n");
471 if (format_ena == true)
472 printf(" end if;\n");
473 printf(" end process;\n");
474 //}}}
475 } // end array
476
477 //{{{
478 if (format_case == true) {
479 if (format_clock == true)
480 printf(" p_rom : process\n");
481 else
482 printf(" p_rom : process(rom_addr)\n");
483 printf(" begin\n");
484 if (format_clock == true)
485 printf(" wait until rising_edge(CLK);\n");
486 if (format_ena == true)
487 printf(" if (ENA = '1') then\n");
488
489 printf(" DATA <= (others => '0');\n");
490 printf(" case rom_addr is\n");
491 for (i = 0; i < rom_size; i ++ ) {
492 printf(" when x\042%03X\042 => DATA <= x\042%02X\042;\n",i,mem[i]);
493 }
494 printf(" when others => DATA <= (others => '0');\n");
495 printf(" end case;\n");
496 if (format_ena == true)
497 printf(" end if;\n");
498 printf(" end process;\n");
499 //}}}
500 } // end case
501 printf("end RTL;\n");
502
503 return 0;
504 }
Impressum, Datenschutz