wbgen2 108 KB
Newer Older
twlostow's avatar
x  
twlostow committed
1 2
#!/usr/bin/env lua
package.preload['alt_getopt']=(function(...)
3
local n,r,u,a,o=type,pairs,ipairs,io,os
twlostow's avatar
x  
twlostow committed
4
module("alt_getopt")
5
local function i(t)
6 7 8 9 10
local e=1
local e=#t
local e={}
for a,t in t:gmatch("(%w)(:?)")do
e[a]=#t
twlostow's avatar
x  
twlostow committed
11
end
12
return e
twlostow's avatar
x  
twlostow committed
13
end
14
local function d(t,e)
15
a.stderr:write(t)
16
o.exit(e)
twlostow's avatar
x  
twlostow committed
17 18
end
local function a(e)
19
d("Unknown option `-"..
twlostow's avatar
x  
twlostow committed
20 21 22 23 24 25
(#e>1 and"-"or"")..e.."'\n",1)
end
local function l(t,e)
if not t[e]then
a(e)
end
26
while n(t[e])=="string"do
twlostow's avatar
x  
twlostow committed
27 28 29 30 31 32 33
e=t[e]
if not t[e]then
a(e)
end
end
return e
end
34
function get_ordered_opts(n,a,s)
twlostow's avatar
x  
twlostow committed
35 36
local t=1
local e=1
37
local o={}
38
local h={}
39 40 41
local i=i(a)
for t,e in r(s)do
i[t]=e
twlostow's avatar
x  
twlostow committed
42 43 44 45 46 47 48 49 50
end
while t<=#n do
local a=n[t]
if a=="--"then
t=t+1
break
elseif a=="-"then
break
elseif a:sub(1,2)=="--"then
51 52 53
local s=a:find("=",1,true)
if s then
local t=a:sub(3,s-1)
54 55 56
t=l(i,t)
if i[t]==0 then
d("Bad usage of option `"..a.."'\n",1)
twlostow's avatar
x  
twlostow committed
57
end
58
h[e]=a:sub(s+1)
59
o[e]=t
twlostow's avatar
x  
twlostow committed
60
else
61
local s=a:sub(3)
62 63 64
s=l(i,s)
if i[s]==0 then
o[e]=s
twlostow's avatar
x  
twlostow committed
65 66
else
if t==#n then
67
d("Missed value for option `"..a.."'\n",1)
twlostow's avatar
x  
twlostow committed
68
end
69
h[e]=n[t+1]
70
o[e]=s
twlostow's avatar
x  
twlostow committed
71 72 73 74 75
t=t+1
end
end
e=e+1
elseif a:sub(1,1)=="-"then
76
local s
77 78 79 80
for r=2,a:len()do
local s=l(i,a:sub(r,r))
if i[s]==0 then
o[e]=s
twlostow's avatar
x  
twlostow committed
81
e=e+1
82
elseif a:len()==r then
twlostow's avatar
x  
twlostow committed
83
if t==#n then
84
d("Missed value for option `-"..s.."'\n",1)
twlostow's avatar
x  
twlostow committed
85
end
86
h[e]=n[t+1]
87
o[e]=s
twlostow's avatar
x  
twlostow committed
88 89 90 91
t=t+1
e=e+1
break
else
92 93
h[e]=a:sub(r+1)
o[e]=s
twlostow's avatar
x  
twlostow committed
94 95 96 97 98 99 100 101 102
e=e+1
break
end
end
else
break
end
t=t+1
end
103
return o,t,h
twlostow's avatar
x  
twlostow committed
104
end
105
function get_opts(t,o,a)
twlostow's avatar
x  
twlostow committed
106
local e={}
107 108 109 110
local a,i,t=get_ordered_opts(t,o,a)
for a,o in u(a)do
if t[a]then
e[o]=t[a]
twlostow's avatar
x  
twlostow committed
111
else
112
e[o]=1
twlostow's avatar
x  
twlostow committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
end
end
return e,i
end
end)
VERBOSE_DEBUG=0;
DATA_BUS_WIDTH=32;
SYNC_CHAIN_LENGTH=3;
TYPE_PERIPH=1;
TYPE_REG=2;
TYPE_FIELD=3;
TYPE_FIFO=4;
TYPE_ENUM=5;
TYPE_RAM=6;
TYPE_IRQ=7;
ALL_REG_TYPES={TYPE_REG,TYPE_RAM,TYPE_FIFO,TYPE_IRQ};
FIFO_FULL=1;
FIFO_EMPTY=2;
FIFO_CLEAR=16;
FIFO_COUNT=32;
BUS_TO_CORE=1;
CORE_TO_BUS=2;
READ_ONLY=1;
READ_WRITE=2;
WRITE_ONLY=4;
SET_ON_WRITE=8;
RESET_ON_WRITE=16;
MONOSTABLE=1;
BIT=2;
SLV=4;
SIGNED=8;
UNSIGNED=16;
ENUM=32;
PASS_THROUGH=64;
INTEGER=128;
EXPRESSION=256;
UNDEFINED=512;
CONSTANT=1024;
LOAD_INT=1;
LOAD_EXT=2;
ACC_RO_WO=1;
ACC_WO_RO=2;
ACC_RW_RW=3;
ACC_RW_RO=4;
FROM_WB=1;
TO_WB=2;
EDGE_RISING=0;
EDGE_FALLING=1;
LEVEL_0=2;
LEVEL_1=3;
function peripheral(e)e['__type']=TYPE_PERIPH;periph=e;return e;end
function reg(e)e['__type']=TYPE_REG;return e;end
function field(e)e['__type']=TYPE_FIELD;return e;end
function fifo_reg(e)e['__type']=TYPE_FIFO;return e;end
function ram(e)e['__type']=TYPE_RAM;return e;end
function enum(e)e['__type']=TYPE_ENUM;return e;end
function irq(e)e['__type']=TYPE_IRQ;return e;end
function dbg(...)
if(VERBOSE_DEBUG~=0)then print(arg);end
end
function chk_nil(e,t)
if(e==nil)then
die(t.." expected.");
end
return e;
end
179 180 181 182 183 184
function range2bits(e)
local t=e[1];
local a=e[2];
local e;
if(math.abs(t)>math.abs(a))then
e=math.abs(t);
twlostow's avatar
x  
twlostow committed
185
else
186
e=math.abs(a);
twlostow's avatar
x  
twlostow committed
187
end
188 189 190
local e=math.ceil(math.log(e)/math.log(2));
if(t<0)then
e=e+1;
twlostow's avatar
x  
twlostow committed
191
end
192
return e;
twlostow's avatar
x  
twlostow committed
193
end
194
function calc_size(e,t)
twlostow's avatar
x  
twlostow committed
195 196
if(e.type==MONOSTABLE or e.type==BIT)then
e.size=1;
197
elseif(e.type==SLV or e.type==PASS_THROUGH)then
twlostow's avatar
x  
twlostow committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
if(e.size==nil)then
die("no size declared for SLV-type field '"..e.name.."'");
end
elseif(e.type==SIGNED or e.type==UNSIGNED)then
if(e.range==nil and e.size==nil)then
die("neither range nor size declared for SIGNED/UNSIGNED-type field '"..e.name.."'");
end
if(e.size==nil)then
local t=range2bits(e.range);
if(t==nil)then
die("misdeclared range for SIGNED/UNSIGNED-type field '"..e.name.."'");
end
e.size=t;
end
elseif(e.type==ENUM)then
die("ENUM-type fields are not yet supported. Sorry :(");
end
215
t.total_size=t.total_size+e.size;
twlostow's avatar
x  
twlostow committed
216
end
217
function foreach_reg(t,a,e)
218 219 220 221
if(e==nil)then
e=periph;
end
for o,e in ipairs(e)do
twlostow's avatar
x  
twlostow committed
222
if(type(e)=='table')then
223 224
if(e.__type~=nil and(match(e.__type,t)))then
a(e);
twlostow's avatar
x  
twlostow committed
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
end
end
end
end
function foreach_field(a)
foreach_reg({TYPE_REG,TYPE_FIFO},function(t)
for o,e in ipairs(t)do
if(type(e)=='table'and e.__type==TYPE_FIELD)then
a(e,t,periph);
end
end
end);
end
function foreach_subfield(t,a)
for o,e in ipairs(t)do
if(type(e)=='table'and e.__type==TYPE_FIELD)then
a(e,t);
end
end
end
function align(t,a)
local e;
if(t.align==nil)then e=1;else e=t.align;end
local e=e*math.floor((a+e-1)/e);
return e;
end
251 252 253 254 255 256 257
function calc_field_offset(e,t)
local a=t.current_offset;
if(t.__type==TYPE_FIFO)then
local o=align(e,a);
if((o%DATA_BUS_WIDTH)+e.size>DATA_BUS_WIDTH)then
e.align=DATA_BUS_WIDTH;
a=align(e,a);
twlostow's avatar
x  
twlostow committed
258 259 260
else
a=o;
end
261 262
t.current_offset=a+e.size;
e.offset=a;
twlostow's avatar
x  
twlostow committed
263
else
264 265 266
a=align(e,a);
t.current_offset=a+e.size;
e.offset=a;
twlostow's avatar
x  
twlostow committed
267
end
268 269 270 271
e.offset_unaligned=t.current_offset_unaligned;
t.current_offset_unaligned=t.current_offset_unaligned+e.size;
if(t.__type==TYPE_REG and t.current_offset>DATA_BUS_WIDTH)then
die("Total size of register '"..t.name.."' ("..t.current_offset..") exceeds data bus width ("..DATA_BUS_WIDTH..")");
twlostow's avatar
x  
twlostow committed
272 273 274 275 276 277 278 279 280 281
end
end
function calc_num_fields(t,e)
if(e.num_fields==nil)then e.num_fields=0;end
e.num_fields=e.num_fields+1;
end
function die(e)
print("Error: "..e);
os.exit(-1);
end
282
function match(t,e)
twlostow's avatar
x  
twlostow committed
283
local a,a;
284 285
for a,e in pairs(e)do
if(t==e)then return true;end
twlostow's avatar
x  
twlostow committed
286 287 288
end
return false;
end
289 290
function inset(t,e)
for a,e in ipairs(e)do if(t==e)then return true;end end
twlostow's avatar
x  
twlostow committed
291 292
return false;
end
293 294
function csel(e,t,a)
if(e)then
295
return t;
296 297
else
return a;
298 299 300 301 302 303 304 305 306 307
end
end
function check_field_types(e)
if(e.type==nil)then
die("no type declared for field: "..e.name);
end
end
function check_obj_names_prefixes(e)
if(e.name==nil)then
die("no name declared for object: "..e.size);
twlostow's avatar
x  
twlostow committed
308 309 310 311 312 313 314 315 316 317 318 319 320
end
end
function fix_prefix(e)
if(e.c_prefix==nil or e.hdl_prefix==nil)then
if(e.prefix==nil and e.__type~=TYPE_FIELD)then
die("No C/HDL prefix nor default prefix defined for field/reg/peripheral '"..e.name.."'");
end
e.c_prefix=e.prefix;
e.hdl_prefix=e.prefix;
return e;
end
return e;
end
321 322
function default_access(e,a,t,o)
if(e.type==a)then
twlostow's avatar
x  
twlostow committed
323
if(e.access_bus==nil)then
324
e.access_bus=t;
twlostow's avatar
x  
twlostow committed
325 326
end
if(e.access_dev==nil)then
327
e.access_dev=o;
twlostow's avatar
x  
twlostow committed
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
end
end
end
function fix_access(e,t)
if(t.__type==TYPE_REG)then
default_access(e,BIT,READ_WRITE,READ_ONLY);
default_access(e,SLV,READ_WRITE,READ_ONLY);
default_access(e,SIGNED,READ_WRITE,READ_ONLY);
default_access(e,UNSIGNED,READ_WRITE,READ_ONLY);
default_access(e,MONOSTABLE,WRITE_ONLY,READ_ONLY);
default_access(e,ENUM,READ_WRITE,READ_ONLY);
default_access(e,PASS_THROUGH,WRITE_ONLY,READ_ONLY);
default_access(e,CONSTANT,READ_ONLY,WRITE_ONLY);
if(e.access~=nil)then
return;
end
if(e.access_bus==READ_ONLY and e.access_dev==WRITE_ONLY)then
e.access=ACC_RO_WO;
elseif(e.access_bus==WRITE_ONLY and e.access_dev==READ_ONLY)then
e.access=ACC_WO_RO;
elseif(e.access_bus==READ_WRITE and e.access_dev==READ_WRITE)then
e.access=ACC_RW_RW;
elseif(e.access_bus==READ_WRITE and e.access_dev==READ_ONLY)then
e.access=ACC_RW_RO;
else
die("Illegal access flags combination for field '"..e.name.."' in register '"..t.name.."'");
end
end
end
function check_max_size(e)
if(e.total_size>DATA_BUS_WIDTH and e.__type==TYPE_REG)then
359
die("register "..e.name.." size exceeds data bus witdh ("..DATA_BUS_WIDTH.." bits)");
twlostow's avatar
x  
twlostow committed
360 361 362 363 364 365 366 367 368 369 370 371
end
end
all_regs_size=0;
max_ram_addr_bits=0;
block_bits=0;
num_rams=0;
function log2(e)
return math.floor(math.log(e)/math.log(2));
end
function log2up(e)
return math.ceil(math.log(e)/math.log(2));
end
372 373 374
function is_power_of_2(e)
for t=1,24 do
if(e==math.pow(2,t))then return true;end
twlostow's avatar
x  
twlostow committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
end
return false;
end
function calc_address_sizes(e)
if(e.__type==TYPE_REG)then
all_regs_size=align(e,all_regs_size)+1;
elseif(e.__type==TYPE_RAM)then
if(not is_power_of_2(e.size))then die("RAM '"..e.name.."': memory size must be a power of 2");end
if(e.wrap_bits==nil)then
e.wrap_bits=0;
end
e.addr_bits=log2(e.size*math.pow(2,e.wrap_bits));
if(max_ram_addr_bits<e.addr_bits)then
max_ram_addr_bits=e.addr_bits;
end
if(e.width>DATA_BUS_WIDTH)then
die("RAM '"..e.name.."' data width exceeds WB data bus width");
end
e.select_bits=csel(periph.regcount+periph.fifocount==0,num_rams,num_rams+1);
num_rams=num_rams+1;
end
regbank_address_bits=log2up(all_regs_size);
end
function assign_addresses()
local o=math.max(max_ram_addr_bits,log2up(all_regs_size));
local e=num_rams;
401
local t=0;
twlostow's avatar
x  
twlostow committed
402 403 404
if(all_regs_size>0)then
e=e+1;
end
405
local a=log2up(e);
twlostow's avatar
x  
twlostow committed
406 407
foreach_reg({TYPE_REG,TYPE_FIFO},function(e)
if(e.__type==TYPE_REG)then
408 409
e.base=align(e,t);
t=e.base+1;
twlostow's avatar
x  
twlostow committed
410 411
end
end);
412 413
address_bus_width=o+a;
address_bus_select_bits=a;
twlostow's avatar
x  
twlostow committed
414
end
415 416
function find_max(e,t)
local a=0;
twlostow's avatar
x  
twlostow committed
417
local o,o;
418 419
for o,e in pairs(e)do if(type(e)=='table'and e[t]~=nil and e[t]>a)then a=e[t];end end
return a;
twlostow's avatar
x  
twlostow committed
420 421 422 423 424 425 426 427 428
end
function table_join(t,e)
local a,a;
if(e==nil)then return;end
for a,e in ipairs(e)do
table.insert(t,e);
end
end
function tree_2_table(e)
429 430 431 432 433
local a={};
foreach_reg({TYPE_REG,TYPE_RAM,TYPE_FIFO,TYPE_IRQ},function(t)
if(t[e]~=nil)then
if(type(t[e])=='table')then
table_join(a,t[e]);
twlostow's avatar
x  
twlostow committed
434
else
435
table.insert(a,t[e]);
twlostow's avatar
x  
twlostow committed
436 437
end
end
438 439 440 441
foreach_subfield(t,function(t,o)
if(t[e]~=nil)then
if(type(t[e])=='table')then
table_join(a,t[e]);
twlostow's avatar
x  
twlostow committed
442
else
443
table.insert(a,t[e]);
twlostow's avatar
x  
twlostow committed
444 445 446 447
end
end
end);
end);
448
return a;
twlostow's avatar
x  
twlostow committed
449
end
450
function remove_duplicates(a)
451
function count_entries(t,a)
twlostow's avatar
x  
twlostow committed
452 453
local o,o,e;
e=0;
454
for o,t in ipairs(t)do if(t==a)then e=e+1;end end
twlostow's avatar
x  
twlostow committed
455 456 457
return e;
end
local e={};
458
for a,t in ipairs(a)do
twlostow's avatar
x  
twlostow committed
459 460 461 462 463 464 465 466
local a=count_entries(e,t);
if(a==0)then
table.insert(e,t);
end
end
return e;
end
function wbgen_count_subblocks()
467
local o=0;
468
local t=0;
twlostow's avatar
x  
twlostow committed
469
local a=0;
470
local e=0;
471
foreach_reg({TYPE_RAM},function(e)o=o+1;end);
472 473 474
foreach_reg({TYPE_REG},function(e)a=a+1;end);
foreach_reg({TYPE_FIFO},function(e)t=t+1;end);
foreach_reg({TYPE_IRQ},function(t)e=e+1;end);
475
periph.ramcount=o;
476 477 478 479
periph.fifocount=t;
periph.regcount=a;
periph.irqcount=e;
if(o+t+a+e==0)then
twlostow's avatar
x  
twlostow committed
480 481 482 483
die("Can't generate an empty peripheral. Define some regs, RAMs, FIFOs or IRQs, please...");
end
end
function deepcopy(i)
484
local o={}
485
local function t(e)
twlostow's avatar
x  
twlostow committed
486 487
if type(e)~="table"then
return e
488 489
elseif o[e]then
return o[e]
twlostow's avatar
x  
twlostow committed
490
end
491 492 493 494
local a={}
o[e]=a
for o,e in pairs(e)do
a[t(o)]=t(e)
twlostow's avatar
x  
twlostow committed
495
end
496
return setmetatable(a,getmetatable(e))
twlostow's avatar
x  
twlostow committed
497
end
498
return t(i)
twlostow's avatar
x  
twlostow committed
499
end
500
function va(a,t)
twlostow's avatar
x  
twlostow committed
501 502
local e={};
e.t="assign";
503 504
e.dst=a;
e.src=t;
twlostow's avatar
x  
twlostow committed
505 506
return e;
end
507
function vi(t,a,o)
twlostow's avatar
x  
twlostow committed
508 509
local e={};
e.t="index";
510 511 512
e.name=t;
e.h=a;
e.l=o;
twlostow's avatar
x  
twlostow committed
513 514
return e;
end
515
function vinstance(t,o,a)
twlostow's avatar
x  
twlostow committed
516 517
local e={};
e.t="instance";
518
e.name=t;
519 520
e.component=o;
e.maps=a;
twlostow's avatar
x  
twlostow committed
521 522
return e;
end
523
function vpm(t,a)
twlostow's avatar
x  
twlostow committed
524 525
local e={};
e.t="portmap";
526 527
e.to=t;
e.from=a;
twlostow's avatar
x  
twlostow committed
528 529
return e;
end
530
function vgm(t,a)
twlostow's avatar
x  
twlostow committed
531 532
local e={};
e.t="genmap";
533 534
e.to=t;
e.from=a;
twlostow's avatar
x  
twlostow committed
535 536
return e;
end
537
function vcombprocess(t,a)
twlostow's avatar
x  
twlostow committed
538 539
local e={};
e.t="combprocess";
540 541
e.slist=t;
e.code=a;
twlostow's avatar
x  
twlostow committed
542 543
return e;
end
544
function vsyncprocess(o,a,t)
twlostow's avatar
x  
twlostow committed
545 546
local e={};
e.t="syncprocess";
547 548 549
e.clk=o;
e.rst=a;
e.code=t;
twlostow's avatar
x  
twlostow committed
550 551
return e;
end
552
function vreset(t,a)
twlostow's avatar
x  
twlostow committed
553 554
local e={};
e.t="reset";
555 556
e.level=t;
e.code=a;
twlostow's avatar
x  
twlostow committed
557 558 559 560 561 562 563 564
return e;
end
function vposedge(t)
local e={};
e.t="posedge";
e.code=t;
return e;
end
565
function vif(t,a,o)
twlostow's avatar
x  
twlostow committed
566 567
local e={};
e.t="if";
568
e.cond={t};
569
e.code=a;
570
e.code_else=o;
twlostow's avatar
x  
twlostow committed
571 572
return e;
end
573 574 575 576 577 578 579
function vgenerate_if(a,t)
local e={};
e.t="generate_if";
e.cond={a};
e.code=t;
return e;
end
580
function vequal(a,t)
twlostow's avatar
x  
twlostow committed
581 582
local e={};
e.t="eq";
583 584
e.a=a;
e.b=t;
twlostow's avatar
x  
twlostow committed
585 586
return e;
end
587
function vand(a,t)
twlostow's avatar
x  
twlostow committed
588 589
local e={};
e.t="and";
590 591
e.a=a;
e.b=t;
twlostow's avatar
x  
twlostow committed
592 593
return e;
end
594
function vor(t,a)
595 596
local e={};
e.t="or";
597 598
e.a=t;
e.b=a;
599 600
return e;
end
twlostow's avatar
x  
twlostow committed
601 602 603 604 605 606
function vnot(t)
local e={};
e.t="not";
e.a=t;
return e;
end
607
function vswitch(a,t)
twlostow's avatar
x  
twlostow committed
608 609
local e={};
e.t="switch";
610 611
e.a=a;
e.code=t;
twlostow's avatar
x  
twlostow committed
612 613
return e;
end
614
function vcase(t,a)
twlostow's avatar
x  
twlostow committed
615 616
local e={};
e.t="case";
617 618
e.a=t;
e.code=a;
twlostow's avatar
x  
twlostow committed
619 620 621 622 623 624 625 626 627 628 629 630 631 632
return e;
end
function vcasedefault(t)
local e={};
e.t="casedefault";
e.code=t;
return e;
end
function vcomment(t)
local e={};
e.t="comment";
e.str=t;
return e;
end
633
function vsub(a,t)
twlostow's avatar
x  
twlostow committed
634 635
local e={};
e.t="sub";
636 637
e.a=a;
e.b=t;
twlostow's avatar
x  
twlostow committed
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
return e;
end
function vothers(t)
local e={}
e.t="others";
e.val=t;
return e;
end
function vopenpin()
local e={}
e.t="openpin";
return e;
end
function vundefined()
local e={}
e.t="undefined";
return e;
end
656
function signal(t,a,o,i)
twlostow's avatar
x  
twlostow committed
657
local e={}
658 659
e.comment=i;
e.type=t;
660 661
e.range=a;
e.name=o;
twlostow's avatar
x  
twlostow committed
662 663
return e;
end
664 665
VPORT_WB=1;
VPORT_REG=2;
666
function port(a,i,o,n,s,t)
twlostow's avatar
x  
twlostow committed
667
local e={}
668
e.comment=s;
669
e.type=a;
670 671 672
e.range=i;
e.name=n;
e.dir=o;
673 674
if(t~=nil)then
if(t==VPORT_WB)then
twlostow's avatar
x  
twlostow committed
675
e.is_wb=true;
676 677
e.is_reg_port=false;
elseif(t==VPORT_REG)then
twlostow's avatar
x  
twlostow committed
678
e.is_wb=false;
679 680 681 682 683
e.is_reg_port=true;
else
e.is_wb=false
e.is_reg_port=false;
end
twlostow's avatar
x  
twlostow committed
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
end
return e;
end
global_ports={};
global_signals={};
function add_global_signals(e)
table_join(global_signals,e);
end
function add_global_ports(e)
table_join(global_ports,e);
end
function cgen_build_clock_list()
local e=tree_2_table("clock");
local t,t;
local t={};
e=remove_duplicates(e);
for a,e in pairs(e)do
table.insert(t,port(BIT,0,"in",e,"",true));
end
return t;
end
function cgen_build_siglist()
local e={};
local t,t;
local t;
e=tree_2_table("signals");
table_join(e,global_signals);
for t,e in pairs(e)do
dbg("SIGNAL: ",e.name);
end
return e;
end
function cgen_build_portlist()
local e={};
table_join(e,global_ports);
table_join(e,cgen_build_clock_list());
table_join(e,tree_2_table("ports"));
return e;
end
723 724 725 726 727 728 729 730 731 732 733 734 735
function cgen_build_optional_list()
local a={}
local o={}
local e=1
for i,t in pairs(tree_2_table("optional"))do
if a[t]==nil then
a[t]=1
o[e]=t
e=e+1
end
end
return o
end
twlostow's avatar
x  
twlostow committed
736 737 738
function cgen_find_sigport(e)
for a,t in pairs(g_portlist)do if(e==t.name)then return t;end end
for a,t in pairs(g_siglist)do if(e==t.name)then return t;end end
739 740 741 742 743 744
for a,t in pairs(g_optlist)do if(e==t)then
local e={}
e.type=INTEGER;
e.name=t;
return e;
end end
twlostow's avatar
x  
twlostow committed
745 746 747 748 749 750
die("cgen internal error: undefined signal '"..e.."'");
return nil;
end
function cgen_build_signals_ports()
g_portlist=cgen_build_portlist();
g_siglist=cgen_build_siglist();
751
g_optlist=cgen_build_optional_list();
twlostow's avatar
x  
twlostow committed
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
end
cur_indent=0;
function indent_zero()
cur_indent=0;
end
function indent_left()
cur_indent=cur_indent-1;
end
function indent_right()
cur_indent=cur_indent+1;
end
function cgen_new_snippet()
emit_code="";
end
function emiti()
local e;
for e=1,cur_indent do emit_code=emit_code.."  ";end
end
function emit(e)
local t;
for e=1,cur_indent do emit_code=emit_code.."  ";end
emit_code=emit_code..e.."\n";
end
function emitx(e)
emit_code=emit_code..e;
end
function cgen_get_snippet()
return emit_code;
end
function cgen_write_current_snippet()
output_code_file.write(output_code_file,emit_code);
end
function cgen_write_snippet(e)
output_code_file.write(output_code_file,e);
end
function cgen_generate_init(e)
output_code_file=io.open(e,"w");
if(output_code_file==nil)then
die("Can't open code output file: "..e);
end
end
function cgen_generate_done()
output_code_file.close(output_code_file);
end
function cgen_gen_vlog_constants(t)
local e=io.open(t,"w");
if(e==nil)then
die("can't open "..t.." for writing.");
end
foreach_reg({TYPE_REG},function(a)
802
e.write(e,string.format("`define %-30s %d'h%x\n","ADDR_"..string.upper(periph.c_prefix.."_"..a.c_prefix),address_bus_width+2,(DATA_BUS_WIDTH/8)*a.base));
twlostow's avatar
x  
twlostow committed
803 804 805 806 807 808 809 810 811 812
foreach_subfield(a,function(t)
if(t.c_prefix~=nil)then
e.write(e,string.format("`define %s_%s_%s_OFFSET %d\n",string.upper(periph.c_prefix),string.upper(a.c_prefix),string.upper(t.c_prefix),t.offset));
e.write(e,string.format("`define %s_%s_%s 32'h%08x\n",string.upper(periph.c_prefix),string.upper(a.c_prefix),string.upper(t.c_prefix),(math.pow(2,t.size)-1)*math.pow(2,t.offset)));
end
end);
end);
foreach_reg({TYPE_RAM},function(t)
local a=t.select_bits*
math.pow(2,address_bus_width-address_bus_select_bits);
813 814
e.write(e,string.format("`define %-30s %d'h%x\n","BASE_"..string.upper(periph.c_prefix.."_"..t.c_prefix),address_bus_width+2,(DATA_BUS_WIDTH/8)*a));
e.write(e,string.format("`define %-30s 32'h%x\n","SIZE_"..string.upper(periph.c_prefix.."_"..t.c_prefix),t.size));
twlostow's avatar
x  
twlostow committed
815 816 817 818 819 820 821 822 823 824
end);
io.close(e);
end
fieldtype_2_vhdl={};
fieldtype_2_vhdl[BIT]="std_logic";
fieldtype_2_vhdl[MONOSTABLE]="std_logic";
fieldtype_2_vhdl[SIGNED]="signed";
fieldtype_2_vhdl[UNSIGNED]="unsigned";
fieldtype_2_vhdl[ENUM]="std_logic_vector";
fieldtype_2_vhdl[SLV]="std_logic_vector";
825 826
function gen_vhdl_bin_literal(i,a)
if(a==1)then
827 828
return string.format("'%d'",csel(i==0,0,1));
end
829 830
local e='\"';
local s,o,n,t;
831
o=i;
832
t=math.pow(2,a-1);
833
if(i==nil)then
834 835
for t=1,a do
e=e.."X";
836 837
end
else
838
for a=1,a do
839 840 841 842
n=math.floor(o/t);
e=e..csel(n>0,"1","0");
o=o%t;
t=t/2;
twlostow's avatar
x  
twlostow committed
843
end
844
end
845
return e..'\"';
846 847 848
end
function strip_periph_prefix(e)
return string.gsub(e,"^"..periph.hdl_prefix.."\_","")
twlostow's avatar
x  
twlostow committed
849
end
850 851 852 853 854 855
function port2record(e)
if(options.hdl_reg_style~="record")then
return e
end
for a,t in ipairs(g_portlist)do
if(t.name==e and t.is_reg_port)then
856
return csel(t.dir=="in","regs_i.","regs_o.")..strip_periph_prefix(e)
857 858 859 860 861
end
end
return e
end
function cgen_vhdl_package()
862 863
local t=periph.hdl_prefix.."_wbgen2_pkg";
emit("package "..t.." is")
864
indent_right();
865 866 867 868 869 870 871 872 873 874 875 876 877
emit("");
emit("");
emit("-- Input registers (user design -> WB slave)");
emit("");
cgen_vhdl_port_struct("in");
emit("");
emit("-- Output registers (WB slave -> user design)");
emit("");
cgen_vhdl_port_struct("out");
indent_left();
local e="t_"..periph.hdl_prefix.."_in_registers";
emit("function \"or\" (left, right: "..e..") return "..e..";");
emit("function f_x_to_zero (x:std_logic) return std_logic;");
878
emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector;");
879 880 881 882 883 884 885 886 887 888 889 890 891
indent_left();
indent_left();
emit("end package;");
emit("");
emit("package body "..t.." is");
emit("function f_x_to_zero (x:std_logic) return std_logic is");
emit("begin");
emit("if(x = 'X' or x = 'U') then");
emit("return '0';");
emit("else");
emit("return x;");
emit("end if; ");
emit("end function;");
892 893 894 895 896 897 898 899 900 901 902 903
emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector is");
emit("variable tmp: std_logic_vector(x'length-1 downto 0);");
emit("begin");
emit("for i in 0 to x'length-1 loop");
emit("if(x(i) = 'X' or x(i) = 'U') then");
emit("tmp(i):= '0';");
emit("else");
emit("tmp(i):=x(i);");
emit("end if; ");
emit("end loop; ");
emit("return tmp;");
emit("end function;");
904 905 906 907 908 909 910
emit("function \"or\" (left, right: "..e..") return "..e.." is");
emit("variable tmp: "..e..";");
emit("begin");
for e=1,table.getn(g_portlist)do
local e=g_portlist[e];
if(e.is_reg_port==true and e.dir=="in")then
local e=strip_periph_prefix(e.name);
911
emit("tmp."..e.." := f_x_to_zero(left."..e..") or f_x_to_zero(right."..e..");");
912 913 914 915 916 917
end
end
emit("return tmp;");
emit("end function;");
emit("end package body;");
end
918 919
function cgen_vhdl_port_struct(o)
emit("type t_"..periph.hdl_prefix.."_"..o.."_registers is record");
920
indent_right();
921 922 923 924 925
local a={};
for e=1,table.getn(g_portlist)do
local e=g_portlist[e];
if(e.is_reg_port==true and e.dir==o)then
table.insert(a,e);
926 927
end
end
928 929 930 931 932
for t,e in ipairs(a)do
local t=csel(e.type==SLV and e.range==1,"std_logic",fieldtype_2_vhdl[e.type]);
local t=string.format("%-40s : %s",strip_periph_prefix(e.name),t);
if(e.range>1)then
t=t.."("..(e.range-1).." downto 0)";
933
end
934 935
t=t..";";
emit(t);
936 937 938 939
end
emit("end record;");
indent_left();
emit("");
940
emit("constant c_"..periph.hdl_prefix.."_"..o.."_registers_init_value: t_"..periph.hdl_prefix.."_"..o.."_registers := (");
941
indent_right();
942 943 944 945
for e=1,table.getn(a)do
local t=a[e];
line=strip_periph_prefix(t.name).." => ";
if(t.range>1)then
946
line=line.."(others => '0')"
947
else
948
line=line.."'0'"
949
end
950
if(e~=table.getn(a))then
951 952 953 954 955 956 957
line=line..",";
end
emit(line);
end
emit(");");
end
function cgen_vhdl_header(e)
twlostow's avatar
x  
twlostow committed
958 959 960
emit("---------------------------------------------------------------------------------------");
emit("-- Title          : Wishbone slave core for "..periph.name);
emit("---------------------------------------------------------------------------------------");
961
emit("-- File           : "..e);
twlostow's avatar
x  
twlostow committed
962 963 964 965 966 967 968 969 970 971 972 973
emit("-- Author         : auto-generated by wbgen2 from "..input_wb_file);
emit("-- Created        : "..os.date());
emit("-- Standard       : VHDL'87");
emit("---------------------------------------------------------------------------------------");
emit("-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE "..input_wb_file);
emit("-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!");
emit("---------------------------------------------------------------------------------------");
emit("");
emit("library ieee;");
emit("use ieee.std_logic_1164.all;");
emit("use ieee.numeric_std.all;");
if(periph.ramcount>0 or periph.fifocount>0 or periph.irqcount>0)then
974
emit("use work.wbgen2_pkg.all;");
twlostow's avatar
x  
twlostow committed
975 976 977 978
end
emit("");
end
function cgen_vhdl_entity()
979 980 981 982 983
local e;
if(options.hdl_reg_style=="record")then
emit("use work."..periph.hdl_prefix.."_wbgen2_pkg.all;");
emit("\n");
end
twlostow's avatar
x  
twlostow committed
984 985
emit("entity "..periph.hdl_entity.." is");
indent_right();
986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
if(table.getn(g_optlist)~=0)then
emit("generic (");
indent_right();
emiti()
for t,e in pairs(g_optlist)do
emiti();
emitx(e.." : integer := 1");
if(t~=table.getn(g_optlist))then
emit(";")
else
emit(");")
end
end
indent_left();
end
indent_left();
indent_right();
twlostow's avatar
x  
twlostow committed
1003 1004
emit("port (");
indent_right();
1005 1006 1007
for a=1,table.getn(g_portlist)do
local e=g_portlist[a];
if(options.hdl_reg_style=="signals"or not e.is_reg_port)then
twlostow's avatar
x  
twlostow committed
1008 1009 1010 1011
if(e.comment~=nil and e.comment~="")then
emitx("-- "..e.comment.."\n");
end
local t=string.format("%-40s : %-6s %s",e.name,e.dir,fieldtype_2_vhdl[e.type]);
1012
if(e.range>1 or e.type==SLV)then
twlostow's avatar
x  
twlostow committed
1013 1014
t=t.."("..(e.range-1).." downto 0)";
end
1015
t=t..csel((a==table.getn(g_portlist))and not(options.hdl_reg_style=="record"),"",";");
twlostow's avatar
x  
twlostow committed
1016 1017
emit(t);
end
1018 1019
end
if(options.hdl_reg_style=="record")then
1020 1021
emit(string.format("%-40s : %-6s %s","regs_i","in","t_"..periph.hdl_prefix.."_in_registers;"));
emit(string.format("%-40s : %-6s %s","regs_o","out","t_"..periph.hdl_prefix.."_out_registers"));
1022
end
twlostow's avatar
x  
twlostow committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
indent_left();
emit(");");
indent_left();
emit("end "..periph.hdl_entity..";");
emit("");
emit("architecture syn of "..periph.hdl_entity.." is");
emit("");
for t,e in pairs(g_siglist)do
s=string.format("signal %-40s : %-15s",e.name,fieldtype_2_vhdl[e.type]);
if(e.range>0 and e.type~=BIT)then
s=s..string.format("(%d downto 0)",e.range-1);
end
s=s..";";
emit(s);
end
emit("");
emit("begin");
indent_right();
end
function cgen_vhdl_ending()
indent_left();
emit("end syn;");
end
function cgen_generate_vhdl_code(i)
function find_code(e,t)
for a,e in ipairs(e)do if((e.t~=nil)and(e.t==t))then return e;end end
return nil;
end
function cgen_vhdl_syncprocess(e)
emit("process ("..e.clk..", "..e.rst..")");
emit("begin");
indent_right();
local t=find_code(e.code,"reset");
local a=find_code(e.code,"posedge");
if(a==nil)then die("vhdl code generation error: no vposedge defined for vsyncprocess");end
if(options.reset_type=="asynchronous")then
if(t~=nil)then
emit("if ("..e.rst.." = '"..t.level.."') then ");
indent_right();
recurse(t.code);
indent_left();
emit("elsif rising_edge("..e.clk..") then");
indent_right();
else
emit("if rising_edge("..e.clk..") then");
indent_right();
end
recurse(a.code);
indent_left();
emit("end if;");
else
emit("if rising_edge("..e.clk..") then");
indent_right();
if(t~=nil)then
emit("if ("..e.rst.." = '"..t.level.."') then ");
indent_right();
recurse(t.code);
indent_left();
emit("else ");
end
indent_right();
recurse(a.code);
indent_left();
emit("end if;");
indent_left();
emit("end if;");
end
indent_left();
emit("end process;");
emit("");
emit("");
end
1095 1096
function cgen_vhdl_combprocess(t)
local e=true;
twlostow's avatar
x  
twlostow committed
1097 1098
emiti();
emitx("process (");
1099 1100 1101
for a,t in pairs(t.slist)do
if(e)then
e=false;
twlostow's avatar
x  
twlostow committed
1102 1103 1104
else
emitx(", ");
end
1105
emitx(t);
twlostow's avatar
x  
twlostow committed
1106 1107 1108 1109
end
emit(")");
emit("begin");
indent_right();
1110
recurse(t.code);
twlostow's avatar
x  
twlostow committed
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
indent_left();
emit("end process;");
emit("");
emit("");
end
function node_typesize(t)
local e={};
local a;
e.node=t;
if(type(t)=="table")then
if(t.t~=nil and t.t=="index")then
a=cgen_find_sigport(t.name);
e.h=t.h;
e.l=t.l;
e.name=a.name;
e.type=a.type;
if(e.l==nil)then
e.size=1;
e.type=BIT;
else
e.size=e.h-e.l+1;
end
return e;
elseif(t.t~=nil and t.t=="undefined")then
e.type=UNDEFINED;
return e;
else
e.type=EXPRESSION;
e.code=t;
return e;
end
elseif(type(t)=="string")then
a=cgen_find_sigport(t);
e.size=a.range;
e.type=a.type;
e.name=t;
return e;
elseif(type(t)=="number")then
e.type=INTEGER;
e.name=t;
e.size=0;
return e;
else
die("vhdl cgen internal error: node_typesize got an unknown node.");
end
end
function gen_subrange(e)
1158
local t=port2record(e.name);
twlostow's avatar
x  
twlostow committed
1159 1160 1161 1162
if(type(e.node)=="table"and e.node.t=="openpin")then
return"open";
end
if(e.h~=nil and(e.l==nil or(e.l==e.h)))then
1163
return t.."("..e.h..")";
twlostow's avatar
x  
twlostow committed
1164
elseif(e.h~=nil and e.l~=nil)then
1165
return t.."("..e.h.." downto "..e.l..")";
twlostow's avatar
x  
twlostow committed
1166
else
1167
return t;
twlostow's avatar
x  
twlostow committed
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
end
end
function calc_size(e)
if(e.h~=nil and e.l==nil)then
return 1;
elseif(e.h~=nil and e.l~=nil)then
return e.h-e.l+1;
else
local e=cgen_find_sigport(e.name);
return e.range;
end
end
function gen_vhdl_typecvt(t,e)
if(t.type==e.type)then
return(gen_subrange(e));
elseif(e.type==UNDEFINED)then
return"'X'"
elseif(e.type==INTEGER)then
if(t.type==BIT)then
return("'"..e.name.."'");
elseif(t.type==SLV)then
return gen_vhdl_bin_literal(e.name,calc_size(t));
elseif(t.type==SIGNED)then
return("to_signed("..e.name..", "..calc_size(t)..")");
elseif(t.type==UNSIGNED)then
return("to_unsigned("..e.name..", "..calc_size(t)..")");
else die("unsupported assignment: "..t.name.." "..e.name);end
elseif(e.type==BIT)then
if(t.type==SLV)then
return(gen_subrange(e));
else die("unsupported assignment: "..t.name.." "..e.name);end
elseif(e.type==SIGNED or e.type==UNSIGNED)then
if(t.type==SLV)then
return("std_logic_vector("..gen_subrange(e)..")");
else die("unsupported assignment: "..t.name.." "..e.name);end
elseif(e.type==SLV)then
if(t.type==SIGNED)then
return("signed("..gen_subrange(e)..")");
elseif(t.type==UNSIGNED)then
return("unsigned("..gen_subrange(e)..")");
elseif(t.type==BIT)then
return gen_subrange(e);
else
die("unsupported assignment: "..t.name.." "..e.name);end
else die("unsupported assignment: "..t.name.." "..e.name);end
end
1214 1215 1216 1217
function cgen_vhdl_assign(t)
local e=node_typesize(t.dst);
local t=node_typesize(t.src);
if(t.type==EXPRESSION)then
twlostow's avatar
x  
twlostow committed
1218
emiti();
1219 1220
emitx(gen_subrange(e).." <= ");
recurse({t.code});
twlostow's avatar
x  
twlostow committed
1221 1222
emitx(";\n");
else
1223
emit(gen_subrange(e).." <= "..gen_vhdl_typecvt(e,t)..";");
twlostow's avatar
x  
twlostow committed
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
end
end
function cgen_vhdl_if(e)
emiti();emitx("if (");
recurse(e.cond);
emitx(") then\n");
if(e.code_else~=nil)then
indent_right();recurse(e.code);indent_left();
emit("else");
indent_right();recurse(e.code_else);indent_left();
emit("end if;");
else
indent_right();recurse(e.code);indent_left();
emit("end if;");
end
end
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
function cgen_vhdl_generate_if(e)
if(g_gen_block_count==nil)then
g_gen_block_count=0
else
g_gen_block_count=g_gen_block_count+1
end
gname=string.format("genblock_%d",g_gen_block_count)
emiti();emitx(gname..": if (");
recurse(e.cond);
emitx(") generate\n");
indent_right();recurse(e.code);indent_left();
emit("end generate "..gname..";");
end
function cgen_vhdl_not(e)
local t=node_typesize(e.a);
twlostow's avatar
x  
twlostow committed
1255
emitx("not ");
1256 1257
if(t.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
twlostow's avatar
x  
twlostow committed
1258
else
1259
emitx(gen_subrange(t));
twlostow's avatar
x  
twlostow committed
1260 1261
end
end
1262 1263 1264 1265
function cgen_vhdl_binary_op(t)
local a=node_typesize(t.a);
local o=node_typesize(t.b);
local e=t.t;
twlostow's avatar
x  
twlostow committed
1266
if(a.type==EXPRESSION)then
1267
emitx("(");recurse({t.a});emitx(")");
twlostow's avatar
x  
twlostow committed
1268 1269 1270
else
emitx(gen_subrange(a));
end
1271 1272 1273 1274 1275
if(e=="eq")then emitx(" = ");end
if(e=="and")then emitx(" and ");end
if(e=="or")then emitx(" or ");end
if(e=="sub")then emitx(" - ");end
if(e=="add")then emitx(" + ");end
twlostow's avatar
x  
twlostow committed
1276
if(o.type==EXPRESSION)then
1277
emitx("(");recurse({t.b});emitx(")");
twlostow's avatar
x  
twlostow committed
1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
else
emitx(gen_vhdl_typecvt(a,o));
end
end
function cgen_vhdl_comment(e)
emitx("-- "..e.str.."\n");
end
function cgen_vhdl_switch(e)
local t=node_typesize(e.a);
emiti();emitx("case ");
if(t.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
else
local e={};
e.type=SLV;
emitx(gen_vhdl_typecvt(e,t));
end
emitx(" is\n");
for a,e in pairs(e.code)do
if(e.t=="case")then
emit("when "..gen_vhdl_bin_literal(e.a,t.size).." => ");
indent_right();
recurse({e.code});
indent_left();
elseif(e.t=="casedefault")then
emit("when others =>");
indent_right();
recurse({e.code});
indent_left();
end
end
emit("end case;");
end
function cgen_vhdl_instance(t)
1312
local o=0;
1313
local a=0;
twlostow's avatar
x  
twlostow committed
1314 1315 1316 1317
local e;
emit(t.name.." : "..t.component);
for t,e in pairs(t.maps)do
if(e.t=="genmap")then
1318
a=a+1;
1319 1320
elseif(e.t=="portmap")then
o=o+1;
twlostow's avatar
x  
twlostow committed
1321 1322
end
end
1323
if(a>0)then
twlostow's avatar
x  
twlostow committed
1324 1325 1326 1327
indent_right();
emit("generic map (");
indent_right();
e=1;
1328
for o,t in pairs(t.maps)do
twlostow's avatar
x  
twlostow committed
1329
if(t.t=="genmap")then
1330
emit(string.format("%-20s => %s",t.to,t.from)..csel(e==a,"",","));
twlostow's avatar
x  
twlostow committed
1331 1332 1333 1334 1335 1336 1337
e=e+1;
end
end
indent_left();
emit(")");
indent_left();
end
1338
if(o>0)then
twlostow's avatar
x  
twlostow committed
1339 1340 1341 1342
indent_right();
emit("port map (");
indent_right();
e=1;
1343
for a,t in pairs(t.maps)do
twlostow's avatar
x  
twlostow committed
1344
if(t.t=="portmap")then
1345 1346
local a=node_typesize(t.from);
emit(string.format("%-20s => %s",t.to,gen_subrange(a))..csel(e==o,"",","));
twlostow's avatar
x  
twlostow committed
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
e=e+1;
end
end
indent_left();
emit(");");
indent_left();
end
emit("");
end
function cgen_vhdl_others(e)
emitx("(others => '"..e.val.."')");
end
function cgen_vhdl_openpin(e)
emitx("open");
end
function recurse(e)
local t={
["comment"]=cgen_vhdl_comment;
["syncprocess"]=cgen_vhdl_syncprocess;
["combprocess"]=cgen_vhdl_combprocess;
["assign"]=cgen_vhdl_assign;
["if"]=cgen_vhdl_if;
1369
["generate_if"]=cgen_vhdl_generate_if;
twlostow's avatar
x  
twlostow committed
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
["eq"]=cgen_vhdl_binary_op;
["add"]=cgen_vhdl_binary_op;
["sub"]=cgen_vhdl_binary_op;
["or"]=cgen_vhdl_binary_op;
["and"]=cgen_vhdl_binary_op;
["not"]=cgen_vhdl_not;
["switch"]=cgen_vhdl_switch;
["instance"]=cgen_vhdl_instance;
["others"]=cgen_vhdl_others;
["openpin"]=cgen_vhdl_openpin;
};
for a,e in pairs(e)do
if(e.t==nil)then
recurse(e);
else
local t=t[e.t];
if(t==nil)then
die("Unimplemented generator: "..e.t);
end
t(e);
end
end
end
1393 1394
if(options.hdl_reg_style=="record"and options.output_package_file~=nil)then
cgen_generate_init(options.output_package_file);
twlostow's avatar
x  
twlostow committed
1395
cgen_new_snippet();
1396 1397 1398 1399 1400 1401 1402 1403
cgen_vhdl_header(options.output_package_file);
cgen_vhdl_package();
cgen_write_current_snippet();
cgen_generate_done();
end
cgen_generate_init(options.output_hdl_file)
cgen_new_snippet();
cgen_vhdl_header(options.output_hdl_file);
twlostow's avatar
x  
twlostow committed
1404 1405 1406 1407
cgen_vhdl_entity();
recurse(i);
cgen_vhdl_ending();
cgen_write_current_snippet();
1408
cgen_generate_done();
twlostow's avatar
x  
twlostow committed
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478
end
VLOG_WIRE=1;
VLOG_REG=2;
function cgen_verilog_header()
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("// Title          : Wishbone slave core for "..periph.name);
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("// File           : "..options.output_hdl_file);
emit("// Author         : auto-generated by wbgen2 from "..input_wb_file);
emit("// Created        : "..os.date());
emit("// Standard       : Verilog 2001");
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("// THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE "..input_wb_file);
emit("// DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!");
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("");
end
function cgen_verilog_module()
local a;
indent_zero();
emit("module "..periph.hdl_entity.." (");
indent_right();
for t=1,table.getn(g_portlist)do
local e=g_portlist[t];
if(t==table.getn(g_portlist))then
a=true;
else
a=false;
end
if(e.comment~=nil)then
emitx("// "..e.comment.."\n");
end
local t;
if(e.dir=="in")then
t="input";
elseif(e.dir=="out")then
t="output";
elseif(e.dir=="inout")then
dirst="inout";
end
if(e.vlog_type==VLOG_REG)then
t=t.." reg";
end
local o="";
if(e.range>0)then
o="["..(e.range-1)..":0]";
end
local e=string.format("%-11s %-6s %s",t,o,e.name);
e=e..csel(a,"",",");
emit(e);
end
indent_left();
emit(");");
indent_left();
emit("");
for t,e in pairs(g_siglist)do
local a=csel(e.vlog_type==VLOG_REG,"reg","wire");
local t="";
if(e.range>0)then
t=string.format("[%d:0] ",e.range-1);
end
emit(string.format("%-5s %-7s %s;",a,t,e.name));
end
emit("");
indent_right();
end
function cgen_verilog_ending()
indent_left();
emit("endmodule");
end
1479
function cgen_generate_verilog_code(i)
twlostow's avatar
x  
twlostow committed
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
local a=false;
function find_code(e,t)
for a,e in ipairs(e)do if((e.t~=nil)and(e.t==t))then return e;end end
return nil;
end
function cgen_verilog_syncprocess(t)
local e=find_code(t.code,"reset");
if(e~=nil and options.reset_type=="asynchronous")then
emit("always @(posedge "..t.clk.." or "..csel(e.level==0,"negedge","posedge").." rst_n_i) begin")
else
emit("always @(posedge "..t.clk..") begin");
end
indent_right();
a=true;
local o=find_code(t.code,"posedge");
if(o==nil)then die("verilog code generation error: no vposedge defined for vsyncprocess");end
if(e~=nil)then
emit("if ("..t.rst.." == 1'b"..e.level..") begin ");
indent_right();
recurse(e.code);
indent_left();
emit("end else begin");
indent_right();
end
recurse(o.code);
if(e~=nil)then
indent_left();
emit("end");
end
indent_left();
emit("end");
emit("");
a=false;
end
function node_typesize(t)
local e={};
local a;
e.node=t;
if(type(t)=="table")then
if(t.t~=nil)then
if(t.t=="index")then
a=cgen_find_sigport(t.name);
e.h=t.h;
e.l=t.l;
e.sig=a;
e.name=a.name;
e.type=a.type;
if(e.l~=nil)then
e.size=e.h-e.l+1;
else
e.size=1;
end
return e;
elseif(t.t=="others")then
e.type=OTHERS;
e.size=0;
e.value=t.val;
return e;
elseif(t.t=="undefined")then
e.type=UNDEFINED;
return e;
else
e.type=EXPRESSION;
e.code=t;
return e;
end
end
elseif(type(t)=="string")then
a=cgen_find_sigport(t);
e.sig=a;
e.size=a.range;
e.type=a.type;
e.name=t;
return e;
elseif(type(t)=="number")then
e.type=INTEGER;
e.name=t;
e.size=0;
return e;
else
die("node_typesize(): unknown node?");
end
end
function gen_subrange(e)
if(type(e.node)=="table"and e.node.t=="openpin")then
return"";
end
if(e.h~=nil and e.l==nil)then
return e.name.."["..e.h.."]";
elseif(e.h~=nil and e.l~=nil)then
return e.name.."["..e.h..":"..e.l.."]";
else
return e.name;
end
end
function calc_size(e)
if(e.h~=nil and e.l==nil)then
return 1;
elseif(e.h~=nil and e.l~=nil)then
return e.h-e.l+1;
else
local e=cgen_find_sigport(e.name);
return e.range;
end
end
function cgen_verilog_assign(e)
local t=node_typesize(e.dst);
local e=node_typesize(e.src);
t.sig.vlog_type=csel(a,VLOG_REG,VLOG_WIRE);
emiti();
if(e.type==OTHERS or e.type==UNDEFINED)then
local o=string.format("%d'b",t.size);
local e=csel(e.type==UNDEFINED,"X",csel(e.value==1,"1","0"));
for t=1,t.size do
o=o..e;
end
emitx(csel(not a,"assign ","")..gen_subrange(t)..csel(a," <= "," = "));
emitx(o..";\n");
elseif(e.type==EXPRESSION)then
emitx(csel(not a,"assign ","")..gen_subrange(t)..csel(a," <= "," = "));
recurse({e.code});
emitx(";\n");
else
emitx(csel(not a,"assign ","")..gen_subrange(t)..csel(a," <= "," = ")..gen_subrange(e)..";\n");
end
end
function cgen_verilog_if(e)
emiti();emitx("if (");
recurse(e.cond);
emitx(") begin\n");
if(e.code_else~=nil)then
indent_right();
recurse(e.code);
indent_left();
emit("end else begin");
indent_right();
recurse(e.code_else);
indent_left();
emit("end");
else
indent_right();
recurse(e.code);
indent_left();
emit("end");
end
end
1626 1627
function cgen_verilog_not(e)
local t=node_typesize(e.a);
twlostow's avatar
x  
twlostow committed
1628
emitx("! ");
1629 1630
if(t.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
twlostow's avatar
x  
twlostow committed
1631
else
1632
emitx(gen_subrange(t));
twlostow's avatar
x  
twlostow committed
1633
end
1634 1635
end
function cgen_verilog_binary_op(e)
1636 1637
local o=node_typesize(e.a);
local a=node_typesize(e.b);
1638
local t=e.t;
1639
if(o.type==EXPRESSION)then
1640
emitx("(");recurse({e.a});emitx(")");
twlostow's avatar
x  
twlostow committed
1641
else
1642
emitx(gen_subrange(o));
twlostow's avatar
x  
twlostow committed
1643
end
1644 1645 1646 1647 1648
if(t=="eq")then emitx(" == ");end
if(t=="and")then emitx(" && ");end
if(t=="or")then emitx(" || ");end
if(</