Commit 50e10c5b authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

TexInfo doc: use macro to define sections/subsections/chapters

parent 2113b3eb
......@@ -32,8 +32,7 @@ end
function cgen_tex_memmap()
local evenodd=0;
local n = 2;
emit("@subsubsection Memory map summary");
emit("@regsection Memory map summary");
emit("@multitable @columnfractions .10 .15 .15 .55")
emit("@headitem Address @tab Type @tab Prefix @tab Name")
......@@ -80,7 +79,7 @@ end
function cgen_texinfo_reg(reg)
emit("@subsubsection @code{"..reg.c_prefix.."} - "..reg.name);
emit("@regsection @code{"..reg.c_prefix.."} - "..reg.name);
cur_reg_no = cur_reg_no + 1;
......
#!/usr/bin/env lua
package.preload['alt_getopt']=(function(...)
local o,r,u,i,a=type,pairs,ipairs,io,os
local i,h,u,o,a=type,pairs,ipairs,io,os
module("alt_getopt")
local function c(e)
local function r(e)
local t=1
local t=#e
local t={}
for a,e in e:gmatch("(%w)(:?)")do
t[a]=#e
for e,a in e:gmatch("(%w)(:?)")do
t[e]=#a
end
return t
end
local function d(t,e)
i.stderr:write(t)
a.exit(e)
local function d(e,t)
o.stderr:write(e)
a.exit(t)
end
local function a(e)
d("Unknown option `-"..
......@@ -23,7 +23,7 @@ local function l(t,e)
if not t[e]then
a(e)
end
while o(t[e])=="string"do
while i(t[e])=="string"do
e=t[e]
if not t[e]then
a(e)
......@@ -31,13 +31,13 @@ end
end
return e
end
function get_ordered_opts(n,a,s)
function get_ordered_opts(n,o,a)
local t=1
local e=1
local i={}
local h={}
local o=c(a)
for e,t in r(s)do
local s={}
local o=r(o)
for e,t in h(a)do
o[e]=t
end
while t<=#n do
......@@ -48,49 +48,49 @@ break
elseif a=="-"then
break
elseif a:sub(1,2)=="--"then
local s=a:find("=",1,true)
if s then
local t=a:sub(3,s-1)
local h=a:find("=",1,true)
if h then
local t=a:sub(3,h-1)
t=l(o,t)
if o[t]==0 then
d("Bad usage of option `"..a.."'\n",1)
end
h[e]=a:sub(s+1)
s[e]=a:sub(h+1)
i[e]=t
else
local s=a:sub(3)
s=l(o,s)
if o[s]==0 then
i[e]=s
local h=a:sub(3)
h=l(o,h)
if o[h]==0 then
i[e]=h
else
if t==#n then
d("Missed value for option `"..a.."'\n",1)
end
h[e]=n[t+1]
i[e]=s
s[e]=n[t+1]
i[e]=h
t=t+1
end
end
e=e+1
elseif a:sub(1,1)=="-"then
local s
local h
for r=2,a:len()do
local s=l(o,a:sub(r,r))
if o[s]==0 then
i[e]=s
local h=l(o,a:sub(r,r))
if o[h]==0 then
i[e]=h
e=e+1
elseif a:len()==r then
if t==#n then
d("Missed value for option `-"..s.."'\n",1)
d("Missed value for option `-"..h.."'\n",1)
end
h[e]=n[t+1]
i[e]=s
s[e]=n[t+1]
i[e]=h
t=t+1
e=e+1
break
else
h[e]=a:sub(r+1)
i[e]=s
s[e]=a:sub(r+1)
i[e]=h
e=e+1
break
end
......@@ -100,14 +100,14 @@ break
end
t=t+1
end
return i,t,h
return i,t,s
end
function get_opts(a,t,o)
function get_opts(t,a,o)
local e={}
local t,i,o=get_ordered_opts(a,t,o)
for a,t in u(t)do
if o[a]then
e[t]=o[a]
local t,i,a=get_ordered_opts(t,a,o)
for o,t in u(t)do
if a[o]then
e[t]=a[o]
else
e[t]=1
end
......@@ -191,10 +191,10 @@ e=e+1;
end
return e;
end
function calc_size(e,a)
function calc_size(e,t)
if(e.type==MONOSTABLE or e.type==BIT)then
e.size=1;
elseif(e.type==SLV)then
elseif(e.type==SLV or e.type==PASS_THROUGH)then
if(e.size==nil)then
die("no size declared for SLV-type field '"..e.name.."'");
end
......@@ -212,7 +212,7 @@ end
elseif(e.type==ENUM)then
die("ENUM-type fields are not yet supported. Sorry :(");
end
a.total_size=a.total_size+e.size;
t.total_size=t.total_size+e.size;
end
function foreach_reg(a,t,e)
if(e==nil)then
......@@ -290,11 +290,21 @@ function inset(t,e)
for a,e in ipairs(e)do if(t==e)then return true;end end
return false;
end
function csel(e,t,a)
if(e)then
return t;
else
function csel(t,a,e)
if(t)then
return a;
else
return e;
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);
end
end
function fix_prefix(e)
......@@ -308,13 +318,13 @@ return e;
end
return e;
end
function default_access(e,o,a,t)
if(e.type==o)then
function default_access(e,t,a,o)
if(e.type==t)then
if(e.access_bus==nil)then
e.access_bus=a;
end
if(e.access_dev==nil)then
e.access_dev=t;
e.access_dev=o;
end
end
end
......@@ -346,7 +356,7 @@ end
end
function check_max_size(e)
if(e.total_size>DATA_BUS_WIDTH and e.__type==TYPE_REG)then
die("register ",e.name," size exceeds data bus witdh (",DATA_BUS_WIDTH," bits)");
die("register "..e.name.." size exceeds data bus witdh ("..DATA_BUS_WIDTH.." bits)");
end
end
all_regs_size=0;
......@@ -359,9 +369,9 @@ end
function log2up(e)
return math.ceil(math.log(e)/math.log(2));
end
function is_power_of_2(e)
for t=1,24 do
if(e==math.pow(2,t))then return true;end
function is_power_of_2(t)
for e=1,24 do
if(t==math.pow(2,e))then return true;end
end
return false;
end
......@@ -388,25 +398,25 @@ end
function assign_addresses()
local o=math.max(max_ram_addr_bits,log2up(all_regs_size));
local e=num_rams;
local a=0;
local t=0;
if(all_regs_size>0)then
e=e+1;
end
local t=log2up(e);
local a=log2up(e);
foreach_reg({TYPE_REG,TYPE_FIFO},function(e)
if(e.__type==TYPE_REG)then
e.base=align(e,a);
a=e.base+1;
e.base=align(e,t);
t=e.base+1;
end
end);
address_bus_width=o+t;
address_bus_select_bits=t;
address_bus_width=o+a;
address_bus_select_bits=a;
end
function find_max(e,t)
local a=0;
function find_max(e,a)
local t=0;
local o,o;
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;
for o,e in pairs(e)do if(type(e)=='table'and e[a]~=nil and e[a]>t)then t=e[a];end end
return t;
end
function table_join(t,e)
local a,a;
......@@ -438,10 +448,10 @@ end);
return a;
end
function remove_duplicates(o)
function count_entries(a,t)
function count_entries(t,a)
local o,o,e;
e=0;
for o,a in ipairs(a)do if(a==t)then e=e+1;end end
for o,t in ipairs(t)do if(t==a)then e=e+1;end end
return e;
end
local e={};
......@@ -455,37 +465,37 @@ return e;
end
function wbgen_count_subblocks()
local t=0;
local o=0;
local a=0;
local e=0;
local o=0;
foreach_reg({TYPE_RAM},function(e)t=t+1;end);
foreach_reg({TYPE_REG},function(t)e=e+1;end);
foreach_reg({TYPE_FIFO},function(e)a=a+1;end);
foreach_reg({TYPE_IRQ},function(e)o=o+1;end);
foreach_reg({TYPE_REG},function(e)a=a+1;end);
foreach_reg({TYPE_FIFO},function(e)o=o+1;end);
foreach_reg({TYPE_IRQ},function(t)e=e+1;end);
periph.ramcount=t;
periph.fifocount=a;
periph.regcount=e;
periph.irqcount=o;
if(t+a+e+o==0)then
periph.fifocount=o;
periph.regcount=a;
periph.irqcount=e;
if(t+o+a+e==0)then
die("Can't generate an empty peripheral. Define some regs, RAMs, FIFOs or IRQs, please...");
end
end
function deepcopy(i)
local t={}
local function o(e)
local function a(e)
if type(e)~="table"then
return e
elseif t[e]then
return t[e]
end
local a={}
t[e]=a
local o={}
t[e]=o
for t,e in pairs(e)do
a[o(t)]=o(e)
o[a(t)]=a(e)
end
return setmetatable(a,getmetatable(e))
return setmetatable(o,getmetatable(e))
end
return o(i)
return a(i)
end
function va(t,a)
local e={};
......@@ -502,12 +512,12 @@ e.h=a;
e.l=o;
return e;
end
function vinstance(a,o,t)
function vinstance(a,t,o)
local e={};
e.t="instance";
e.name=a;
e.component=o;
e.maps=t;
e.component=t;
e.maps=o;
return e;
end
function vpm(t,a)
......@@ -524,26 +534,26 @@ e.to=t;
e.from=a;
return e;
end
function vcombprocess(t,a)
function vcombprocess(a,t)
local e={};
e.t="combprocess";
e.slist=t;
e.code=a;
e.slist=a;
e.code=t;
return e;
end
function vsyncprocess(t,o,a)
function vsyncprocess(o,a,t)
local e={};
e.t="syncprocess";
e.clk=t;
e.rst=o;
e.code=a;
e.clk=o;
e.rst=a;
e.code=t;
return e;
end
function vreset(a,t)
function vreset(t,a)
local e={};
e.t="reset";
e.level=a;
e.code=t;
e.level=t;
e.code=a;
return e;
end
function vposedge(t)
......@@ -574,24 +584,31 @@ e.a=t;
e.b=a;
return e;
end
function vor(a,t)
local e={};
e.t="or";
e.a=a;
e.b=t;
return e;
end
function vnot(t)
local e={};
e.t="not";
e.a=t;
return e;
end
function vswitch(a,t)
function vswitch(t,a)
local e={};
e.t="switch";
e.a=a;
e.code=t;
e.a=t;
e.code=a;
return e;
end
function vcase(a,t)
function vcase(t,a)
local e={};
e.t="case";
e.a=a;
e.code=t;
e.a=t;
e.code=a;
return e;
end
function vcasedefault(t)
......@@ -606,11 +623,11 @@ e.t="comment";
e.str=t;
return e;
end
function vsub(a,t)
function vsub(t,a)
local e={};
e.t="sub";
e.a=a;
e.b=t;
e.a=t;
e.b=a;
return e;
end
function vothers(t)
......@@ -629,26 +646,23 @@ local e={}
e.t="undefined";
return e;
end
function signal(t,o,a,i)
function signal(a,o,i,t)
local e={}
e.comment=i;
e.type=t;
e.comment=t;
e.type=a;
e.range=o;
e.name=a;
e.name=i;
return e;
end
VPORT_WB=1;
VPORT_REG=2;
function port(s,a,n,i,o,t)
function port(s,o,i,a,n,t)
local e={}
e.comment=o;
e.comment=n;
e.type=s;
if(e.type==SLV and a==1)then
e.type=BIT;
end
e.range=a;
e.name=i;
e.dir=n;
e.range=o;
e.name=a;
e.dir=i;
if(t~=nil)then
if(t==VPORT_WB)then
e.is_wb=true;
......@@ -758,7 +772,7 @@ if(e==nil)then
die("can't open "..t.." for writing.");
end
foreach_reg({TYPE_REG},function(a)
e.write(e,string.format("`define %-30s %d'h%x\n","ADDR_"..string.upper(periph.hdl_prefix.."_"..a.hdl_prefix),address_bus_width+2,(DATA_BUS_WIDTH/8)*a.base));
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));
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));
......@@ -769,8 +783,8 @@ end);
foreach_reg({TYPE_RAM},function(t)
local a=t.select_bits*
math.pow(2,address_bus_width-address_bus_select_bits);
e.write(e,string.format("`define %-30s %d'h%x\n","BASE_"..string.upper(periph.hdl_prefix.."_"..t.hdl_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.hdl_prefix.."_"..t.hdl_prefix),t.size));
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));
end);
io.close(e);
end
......@@ -781,23 +795,23 @@ fieldtype_2_vhdl[SIGNED]="signed";
fieldtype_2_vhdl[UNSIGNED]="unsigned";
fieldtype_2_vhdl[ENUM]="std_logic_vector";
fieldtype_2_vhdl[SLV]="std_logic_vector";
function gen_vhdl_bin_literal(i,a)
if(a==1)then
function gen_vhdl_bin_literal(i,o)
if(o==1)then
return string.format("'%d'",csel(i==0,0,1));
end
local t='\"';
local s,o,n,e;
o=i;
e=math.pow(2,a-1);
local s,a,n,e;
a=i;
e=math.pow(2,o-1);
if(i==nil)then
for e=1,a do
for e=1,o do
t=t.."X";
end
else
for a=1,a do
n=math.floor(o/e);
for o=1,o do
n=math.floor(a/e);
t=t..csel(n>0,"1","0");
o=o%e;
a=a%e;
e=e/2;
end
end
......@@ -834,6 +848,7 @@ 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;");
emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector;");
indent_left();
indent_left();
emit("end package;");
......@@ -847,6 +862,18 @@ emit("else");
emit("return x;");
emit("end if; ");
emit("end function;");
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;");
emit("function \"or\" (left, right: "..e..") return "..e.." is");
emit("variable tmp: "..e..";");
emit("begin");
......@@ -854,45 +881,46 @@ 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);
emit("tmp."..e.." := left."..e.." or right."..e..";");
emit("tmp."..e.." := f_x_to_zero(left."..e..") or f_x_to_zero(right."..e..");");
end
end
emit("return tmp;");
emit("end function;");
emit("end package body;");
end
function cgen_vhdl_port_struct(t)
emit("type t_"..periph.hdl_prefix.."_"..t.."_registers is record");
function cgen_vhdl_port_struct(o)
emit("type t_"..periph.hdl_prefix.."_"..o.."_registers is record");
indent_right();
local e={};
for a=1,table.getn(g_portlist)do
local a=g_portlist[a];
if(a.is_reg_port==true and a.dir==t)then
table.insert(e,a);
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);
end
end
for e,t in ipairs(e)do
local e=string.format("%-40s : %s",strip_periph_prefix(t.name),fieldtype_2_vhdl[t.type]);
if(t.range>1)then
e=e.."("..(t.range-1).." downto 0)";
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)";
end
e=e..";";
emit(e);
t=t..";";
emit(t);
end
emit("end record;");
indent_left();
emit("");
emit("constant c_"..periph.hdl_prefix.."_"..t.."_registers_init_value: t_"..periph.hdl_prefix.."_"..t.."_registers := (");
emit("constant c_"..periph.hdl_prefix.."_"..o.."_registers_init_value: t_"..periph.hdl_prefix.."_"..o.."_registers := (");
indent_right();
for t=1,table.getn(e)do
local a=e[t];
line=strip_periph_prefix(a.name).." => ";
if(a.range>1)then
for t=1,table.getn(a)do
local e=a[t];
line=strip_periph_prefix(e.name).." => ";
if(e.range>1)then
line=line.."(others => '0')"
else
line=line.."'0'"
end
if(t~=table.getn(e))then
if(t~=table.getn(a))then
line=line..",";
end
emit(line);
......@@ -936,8 +964,9 @@ if(options.hdl_reg_style=="signals"or not e.is_reg_port)then
if(e.comment~=nil and e.comment~="")then
emitx("-- "..e.comment.."\n");
end
print(e.name.." "..e.type)
local t=string.format("%-40s : %-6s %s",e.name,e.dir,fieldtype_2_vhdl[e.type]);
if(e.range>1)then
if(e.range>1 or e.type==SLV)then
t=t.."("..(e.range-1).." downto 0)";
end
t=t..csel((a==table.getn(g_portlist))and not(options.hdl_reg_style=="record"),"",";");
......@@ -1165,13 +1194,13 @@ indent_right();recurse(e.code);indent_left();
emit("end if;");
end
end
function cgen_vhdl_not(e)
local t=node_typesize(e.a);
function cgen_vhdl_not(t)
local e=node_typesize(t.a);
emitx("not ");
if(t.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
if(e.type==EXPRESSION)then
emitx("(");recurse({t.a});emitx(")");
else
emitx(gen_subrange(t));
emitx(gen_subrange(e));
end
end
function cgen_vhdl_binary_op(t)
......@@ -1390,7 +1419,7 @@ function cgen_verilog_ending()
indent_left();
emit("endmodule");
end
function cgen_generate_verilog_code(i)
function cgen_generate_verilog_code(n)
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
......@@ -1547,23 +1576,23 @@ emitx(gen_subrange(e));
end
end
function cgen_verilog_binary_op(e)
local a=node_typesize(e.a);
local o=node_typesize(e.b);
local o=node_typesize(e.a);
local a=node_typesize(e.b);
local t=e.t;
if(a.type==EXPRESSION)then
if(o.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
else
emitx(gen_subrange(a));
emitx(gen_subrange(o));
end
if(t=="eq")then emitx(" == ");end
if(t=="and")then emitx(" && ");end
if(t=="or")then emitx(" || ");end
if(t=="sub")then emitx(" - ");end
if(t=="add")then emitx(" + ");end
if(o.type==EXPRESSION)then
if(a.type==EXPRESSION)then
emitx("(");recurse({e.b});emitx(")");
else
emitx(gen_subrange(o));
emitx(gen_subrange(a));
end
end
function cgen_verilog_comment(e)
......@@ -1595,29 +1624,29 @@ end
end
emit("endcase");
end
function cgen_verilog_instance(t)
local a=0;
function cgen_verilog_instance(a)
local o=0;
local i=0;
local e;
emitx(t.component.." ");
for t,e in pairs(t.maps)do
emitx(a.component.." ");
for t,e in pairs(a.maps)do
if(e.t=="genmap")then
o=o+1;
i=i+1;
elseif(e.t=="portmap")then
a=a+1;
o=o+1;
end
end
if(o>0)then
if(i>0)then
indent_right();
emit("# (");
indent_right();
e=1;
for t,a in pairs(t.maps)do
for t,a in pairs(a.maps)do
if(a.t=="genmap")then
local t=a.from;
if(t=="true")then t=1;
elseif(t=="false")then t=0;end
emit(string.format(".%-20s(%s)",a.to,t)..csel(e==o,"",","));
emit(string.format(".%-20s(%s)",a.to,t)..csel(e==i,"",","));
e=e+1;
end
end
......@@ -1625,15 +1654,15 @@ indent_left();
emit(")");
indent_left();
end
if(a>0)then
if(o>0)then
indent_right();
emit(t.name.." ( ");
emit(a.name.." ( ");
indent_right();
e=1;
for o,t in pairs(t.maps)do
for a,t in pairs(a.maps)do
if(t.t=="portmap")then
local o=node_typesize(t.from);
emit(string.format(".%-20s(%s)",t.to,gen_subrange(o))..csel(e==a,"",","));
local a=node_typesize(t.from);
emit(string.format(".%-20s(%s)",t.to,gen_subrange(a))..csel(e==o,"",","));
e=e+1;
end
end
......@@ -1700,17 +1729,17 @@ end
end
cgen_new_snippet();
cgen_verilog_header();
local t=cgen_get_snippet();
local a=cgen_get_snippet();
cgen_new_snippet();
recurse(i);
recurse(n);
cgen_verilog_ending();
local e=cgen_get_snippet();
local t=cgen_get_snippet();
cgen_new_snippet();
cgen_verilog_module();
local a=cgen_get_snippet();
cgen_write_snippet(t);
local e=cgen_get_snippet();
cgen_write_snippet(a);
cgen_write_snippet(e);
cgen_write_snippet(t);
end
function cgen_c_field_define(e,a)
local t;
......@@ -1737,6 +1766,7 @@ end
function cgen_c_ramdefs(e)
local t=string.upper(periph.c_prefix).."_"..string.upper(e.c_prefix);
emit("/* definitions for RAM: "..e.name.." */");
emit(string.format("#define "..t.."_BASE 0x%08x %-50s",e.base*DATA_BUS_WIDTH/8,"/* base address */"));
emit(string.format("#define "..t.."_BYTES 0x%08x %-50s",e.size*e.width/8,"/* size in bytes */"));
emit(string.format("#define "..t.."_WORDS 0x%08x %-50s",e.size,"/* size in "..e.width.."-bit words, 32-bit aligned */"));
end
......@@ -1882,21 +1912,21 @@ end
end
return e;
end
function htable_tdstyle(a,t,e)
tbl.data[a][t].style=e;
function htable_tdstyle(e,a,t)
tbl.data[e][a].style=t;
end
function htable_trstyle(t,a,e)
tbl.data[t].style=e;
function htable_trstyle(e,a,t)
tbl.data[e].style=t;
end
function htable_frame(e,t,a,o)
if(o==nil)then
e.data[t][a].extra='style="border: solid 1px black;"';
function htable_frame(a,o,t,e)
if(e==nil)then
a.data[o][t].extra='style="border: solid 1px black;"';
else
e.data[t][a].extra='style="border-left: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
e.data[t][o].extra='style="border-right: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
if(o>a+1)then
for a=a+1,o-1 do
e.data[t][a].extra='border-top: solid 1px black; border-bottom: solid 1px black;';
a.data[o][t].extra='style="border-left: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
a.data[o][e].extra='style="border-right: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
if(e>t+1)then
for e=t+1,e-1 do
a.data[o][e].extra='border-top: solid 1px black; border-bottom: solid 1px black;';
end
end
end
......@@ -1952,27 +1982,27 @@ end
e.rows=a;
end
end
function hlink(e,t)
return'<A href="'..e..'">'..t..'</a>';
function hlink(t,e)
return'<A href="'..t..'">'..e..'</a>';
end
function hitem(e)
return'<li>'..e..'</li>';
end
function hanchor(t,e)
return'<a name="'..t..'">'..e..'</a>';
function hanchor(e,t)
return'<a name="'..e..'">'..t..'</a>';
end
doc_toc={};
function hsection(a,t,o)
function hsection(t,a,o)
local e={};
local i=0;
e.id_mangled="sect_"..a.."_"..t;
e.key=a*1e3+t;
if(t~=0)then
e.id_mangled="sect_"..t.."_"..a;
e.key=t*1e3+a;
if(a~=0)then
e.level=2;
e.id=a.."."..t..".";
e.id=t.."."..a..".";
else
e.level=1;
e.id=a..".";
e.id=t..".";
end
e.name=o;
table.insert(doc_toc,e);
......@@ -2021,23 +2051,23 @@ end
end);
cgen_doc_symbol(t);
end
function cgen_doc_mem_symbol(t)
local e={};
for t,a in pairs(t.ports)do
local t=a;
function cgen_doc_mem_symbol(e)
local t={};
for e,a in pairs(e.ports)do
local e=a;
if(string.find(a.name,"_i")~=nil)then
t.is_wb=true;
e.is_wb=true;
else
t.is_wb=false;
e.is_wb=false;
end
table.insert(e,t);
table.insert(t,e);
end
if(t.clock~=nil)then
local t=port(BIT,0,"in",t.clock);
t.is_wb=true;
table.insert(e,t);
if(e.clock~=nil)then
local e=port(BIT,0,"in",e.clock);
e.is_wb=true;
table.insert(t,e);
end
cgen_doc_symbol(e);
cgen_doc_symbol(t);
end
function cgen_doc_symbol(o)
local t=htable_new(3,5);
......@@ -2101,11 +2131,11 @@ emit('<span style="margin-left: '..((e.level-1)*20)..'px; ">'..e.id.." "..hlink(
end
end
function cgen_doc_memmap()
local o=0;
local i=0;
local a=2;
emit(hsection(1,0,"Memory map summary"));
local i=htable_new(1,5);
local e=i.data[1];
local o=htable_new(1,5);
local e=o.data[1];
e.is_header=true;
e[1].text="H/W Address"
e[2].text="Type";
......@@ -2114,9 +2144,9 @@ e[4].text="VHDL/Verilog prefix";
e[5].text="C prefix";
foreach_reg({TYPE_REG},function(t)
if(t.full_hdl_prefix~=nil)then
htable_add_row(i,a);
local e=i.data[a];a=a+1;
e.style=csel(o,"tr_odd","tr_even");
htable_add_row(o,a);
local e=o.data[a];a=a+1;
e.style=csel(i,"tr_odd","tr_even");
e[1].style="td_code";
e[1].text=string.format("0x%x",t.base);
if(t.doc_is_fiforeg==nil)then
......@@ -2129,48 +2159,48 @@ e[4].style="td_code";
e[4].text=t.full_hdl_prefix;
e[5].style="td_code";
e[5].text=string.upper(t.c_prefix);
o=not o;
i=not i;
end
end);
foreach_reg({TYPE_RAM},function(t)
if(t.full_hdl_prefix~=nil)then
htable_add_row(i,a);
local e=i.data[a];a=a+1;
e.style=csel(o,"tr_odd","tr_even");
e[1].style="td_code";
e[1].text=string.format("0x%x - 0x%x",t.base,t.base+math.pow(2,t.wrap_bits)*t.size-1);
e[2].text="MEM";
e[3].text=hlink("#"..string.upper(t.c_prefix),t.name);
e[4].style="td_code";
e[4].text=t.full_hdl_prefix;
e[5].style="td_code";
e[5].text=string.upper(t.c_prefix);
o=not o;
foreach_reg({TYPE_RAM},function(e)
if(e.full_hdl_prefix~=nil)then
htable_add_row(o,a);
local t=o.data[a];a=a+1;
t.style=csel(i,"tr_odd","tr_even");
t[1].style="td_code";
t[1].text=string.format("0x%x - 0x%x",e.base,e.base+math.pow(2,e.wrap_bits)*e.size-1);
t[2].text="MEM";
t[3].text=hlink("#"..string.upper(e.c_prefix),e.name);
t[4].style="td_code";
t[4].text=e.full_hdl_prefix;
t[5].style="td_code";
t[5].text=string.upper(e.c_prefix);
i=not i;
end
end);
htable_emit(i);
htable_emit(o);
end
function find_field_by_offset(e,a)
local t=nil;
foreach_subfield(e,function(e)if(a>=e.offset and a<=(e.offset+e.size-1))then t=e;end end);
return t;
function find_field_by_offset(e,t)
local a=nil;
foreach_subfield(e,function(e)if(t>=e.offset and t<=(e.offset+e.size-1))then a=e;end end);
return a;
end
function cgen_doc_fieldtable(h,i)
local e=70;
local e;
local t=1;
e=htable_new(2,8);
for t=1,8 do
e.data[1][t].style="td_bit";
e.data[1][t].text=string.format("%d",i+8-t);
local t;
local e=1;
t=htable_new(2,8);
for e=1,8 do
t.data[1][e].style="td_bit";
t.data[1][e].text=string.format("%d",i+8-e);
end
local a=i+7;
while(a>=i)do
local o=find_field_by_offset(h,a);
if(o==nil)then
e.data[2][t].style="td_unused";
e.data[2][t].text="-";
t=t+1;
t.data[2][e].style="td_unused";
t.data[2][e].text="-";
e=e+1;
a=a-1;
else
local n;
......@@ -2181,18 +2211,18 @@ n=o.offset;
end
local s=(a-n)+1;
dbg("ncells: ",s,"bit: ",a,"name: ",o.prefix);
e.data[2][t].colspan=s;
t.data[2][e].colspan=s;
local i;
i=o.c_prefix;
if(i==nil)then i=h.c_prefix;end
e.data[2][t].style="td_field";
e.data[2][t].text=csel(o.size>1,string.format("%s[%d:%d]",string.upper(i),a-o.offset,n-o.offset),string.upper(i));
htable_frame(e,2,t);
t.data[2][e].style="td_field";
t.data[2][e].text=csel(o.size>1,string.format("%s[%d:%d]",string.upper(i),a-o.offset,n-o.offset),string.upper(i));
htable_frame(t,2,e);
a=a-s;
t=t+1;
e=e+1;
end
end
htable_emit(e);
htable_emit(t);
end
function cgen_doc_access(e)
if(e==READ_ONLY)then
......@@ -2292,47 +2322,47 @@ emit("<p>"..string.gsub(t.description,"\n","<br>").."</p>");
end
end
cur_irq_no=1;
function cgen_doc_irq(t)
emit(hanchor(string.upper(t.c_prefix),""));
emit(hsection(5,cur_irq_no,t.name));
function cgen_doc_irq(e)
emit(hanchor(string.upper(e.c_prefix),""));
emit(hsection(5,cur_irq_no,e.name));
cur_irq_no=cur_irq_no+1;
local e=htable_new(3,2);
e.data[1][1].text="<b>HW prefix: </b>";
e.data[2][1].text="<b>C prefix: </b>";
e.data[3][1].text="<b>Trigger: </b>";
e.data[1][2].text=string.lower(periph.hdl_prefix.."_"..t.hdl_prefix);
e.data[2][2].text=string.upper(t.c_prefix);
local t=htable_new(3,2);
t.data[1][1].text="<b>HW prefix: </b>";
t.data[2][1].text="<b>C prefix: </b>";
t.data[3][1].text="<b>Trigger: </b>";
t.data[1][2].text=string.lower(periph.hdl_prefix.."_"..e.hdl_prefix);
t.data[2][2].text=string.upper(e.c_prefix);
local a={
[EDGE_RISING]="rising edge";
[EDGE_FALLING]="falling edge";
[LEVEL_0]="low level";
[LEVEL_1]="high level";
};
e.data[3][2].text=a[t.trigger];
htable_emit(e);
if(t.description~=nil)then
emit("<p>"..string.gsub(t.description,"\n","<br>").."</p>");
t.data[3][2].text=a[e.trigger];
htable_emit(t);
if(e.description~=nil)then
emit("<p>"..string.gsub(e.description,"\n","<br>").."</p>");
end
end
function cgen_generate_documentation()
cgen_new_snippet();cgen_doc_hdl_symbol();local i=cgen_get_snippet();
cgen_new_snippet();cgen_doc_hdl_symbol();local o=cgen_get_snippet();
cgen_new_snippet();
emit(hsection(3,0,"Register description"));
foreach_reg({TYPE_REG},function(e)if(e.no_docu==nil or e.no_docu==false)then cgen_doc_reg(e);end end);
local o=cgen_get_snippet();
local t="";
local i=cgen_get_snippet();
local a="";
if(periph.ramcount>0)then
emit(hsection(4,0,"Memory blocks"));
cgen_new_snippet();
foreach_reg({TYPE_RAM},function(e)if(e.no_docu==nil or e.no_docu==false)then cgen_doc_ram(e);end end);
t=cgen_get_snippet();
a=cgen_get_snippet();
end
local a="";
local t="";
if(periph.irqcount>0)then
cgen_new_snippet();
emit(hsection(5,0,"Interrupts"));
foreach_reg({TYPE_IRQ},function(e)if(e.no_docu==nil or e.no_docu==false)then cgen_doc_irq(e);end end);
a=cgen_get_snippet();
t=cgen_get_snippet();
end
cgen_new_snippet();
cgen_doc_memmap();
......@@ -2340,14 +2370,104 @@ local e=cgen_get_snippet();
cgen_new_snippet();
cgen_doc_header_and_toc();
emit(e);
emit(i);
emit(o);
emit(t);
emit(i);
emit(a);
emit(t);
emit('</BODY>');
emit('</HTML>');
cgen_write_current_snippet();
end
function format_tex_string(e)
e=string.gsub(e," +"," ");
e=string.gsub(e,"^%-","@bullet{} ");
e=string.gsub(e,"\n%-","@*@bullet{} ");
e=string.gsub(e,"\n","@*");
e=string.gsub(e,"<b>","@b{");
e=string.gsub(e,"</b>","}");
e=string.gsub(e,"<i>","@b{");
e=string.gsub(e,"</i>","}");
e=string.gsub(e,"<code>","@code{");
e=string.gsub(e,"</code>","}");
return e
end
function cgen_tex_memmap()
local e=0;
local e=2;
emit("@regsection Memory map summary");
emit("@multitable @columnfractions .10 .15 .15 .55")
emit("@headitem Address @tab Type @tab Prefix @tab Name")
foreach_reg({TYPE_REG},function(e)
if(e.full_hdl_prefix~=nil)then
emit(string.format("@item @code{0x%x} @tab",e.base*4));
if(e.doc_is_fiforeg==nil)then
emit("REG @tab");
else
emit("FIFOREG @tab");
end
emit("@code{"..e.c_prefix.."} @tab");
emit(e.name);
end
end);
foreach_reg({TYPE_RAM},function(e)
if(e.full_hdl_prefix~=nil)then
emit(string.format("@item @code{0x%x - 0x%x}",e.base,e.base+math.pow(2,e.wrap_bits)*e.size-1));
emit("@tab MEM @tab @code{"..e.c_prefix.."} @tab "..e.name);
end
end);
emit("@end multitable ")
end
function cgen_tex_access(e)
if(e==READ_ONLY)then
return"R/O";
elseif(e==READ_WRITE)then
return"R/W";
elseif(e==WRITE_ONLY)then
return"W/O";
else
return"FIXME!";
end
end
function cgen_texinfo_reg(t)
emit("@regsection @code{"..t.c_prefix.."} - "..t.name);
cur_reg_no=cur_reg_no+1;
local e=htable_new(4,2);
if(t.description~=nil)then
emit(t.description);
end
emit("@multitable @columnfractions .10 .10 .15 .10 .55")
emit("@headitem Bits @tab Access @tab Prefix @tab Default @tab Name")
foreach_subfield(t,function(e)
if(e.size==1)then
emit(string.format("@item @code{%d}",e.offset));
else emit(string.format("@item @code{%d...%d}",e.offset+e.size-1,e.offset));
end
emit("@tab "..cgen_tex_access(e.access_bus).." @tab");
if(e.c_prefix==nil)then
emit("@code{"..string.upper(t.c_prefix).."}");
else
emit("@code{"..string.upper(e.c_prefix).."}");
end
emit("@tab @code{X} @tab ");
emit(e.name);
end);
emit("@end multitable");
emit("@multitable @columnfractions 0.15 0.85")
emit("@headitem Field @tab Description")
foreach_subfield(t,function(e)
if(e.description~=nil)then
pfx=csel(e.c_prefix==nil,t.c_prefix,e.c_prefix)
emit("@item @code{"..pfx.."} @tab "..format_tex_string(e.description));
end
end);
emit("@end multitable");
end
function cgen_generate_texinfo_documentation()
cgen_new_snippet();
cgen_tex_memmap();
foreach_reg({TYPE_REG},function(e)if(e.no_docu==nil or e.no_docu==false)then cgen_texinfo_reg(e);end end);
cgen_write_current_snippet();
end
function gen_hdl_field_prefix(a,e)
local t;
if(e.hdl_prefix==nil)then
......@@ -2374,7 +2494,7 @@ t.signals={signal(BIT,0,e.."_dly0"),
signal(BIT,0,e.."_int")};
t.ports={port(BIT,0,"out",e.."_o","Port for MONOSTABLE field: '"..t.name.."' in reg: '"..a.name.."'",VPORT_REG)};
t.acklen=3;
t.extra_code=vsyncprocess("bus_clock_int","rst_n_i",{
t.extra_code=vsyncprocess("clk_sys_i","rst_n_i",{
vreset(0,{
va(e.."_dly0",0);
va(e.."_o",0);
......@@ -2385,8 +2505,7 @@ va(e.."_o",vand(e.."_int",vnot(e.."_dly0")));
};
});
t.reset_code_main={va(e.."_int",0)};
t.write_code={va(e.."_int",vi("wrdata_reg",t.offset)),
va(vi("rddata_reg",t.offset),vundefined())};
t.write_code={va(e.."_int",vi("wrdata_reg",t.offset))};
t.read_code={va(vi("rddata_reg",t.offset),vundefined())};
t.ackgen_code={va(e.."_int",0)};
else
......@@ -2415,7 +2534,7 @@ va(e.."_o",vand(e.."_sync2",vnot(e.."_sync1")));
});};
t.reset_code_main={va(e.."_int",0);
va(e.."_int_delay",0);};
t.write_code={va(vi("rddata_reg",t.offset),vundefined()),
t.write_code={
va(e.."_int",vi("wrdata_reg",t.offset));
va(e.."_int_delay",vi("wrdata_reg",t.offset));};
t.read_code={va(vi("rddata_reg",t.offset),vundefined())};
......@@ -2431,16 +2550,17 @@ if(t.access==ACC_RW_RO)then
t.ports={port(BIT,0,"out",e.."_o","Port for BIT field: '"..t.name.."' in reg: '"..a.name.."'",VPORT_REG)};
t.signals={signal(BIT,0,e.."_int")};
t.acklen=1;
t.write_code={va(vi("rddata_reg",t.offset),vundefined()),
t.write_code={
va(e.."_int",vi("wrdata_reg",t.offset))};
t.read_code={va(vi("rddata_reg",t.offset),e.."_int")};
t.reset_code_main={va(e.."_int",0)};
print("RV: ",t.reset_value)
t.reset_code_main={va(e.."_int",csel(t.reset_value==nil,0,t.reset_value))};
t.extra_code={va(e.."_o",e.."_int")};
elseif(t.access==ACC_RO_WO)then
t.ports={port(BIT,0,"in",e.."_i","Port for BIT field: '"..t.name.."' in reg: '"..a.name.."'",VPORT_REG)};
t.signals={};
t.acklen=1;
t.write_code={va(vi("rddata_reg",t.offset),vundefined())};
t.write_code={};
t.read_code={va(vi("rddata_reg",t.offset),e.."_i")};
t.reset_code_main={};
t.extra_code={};
......@@ -2453,7 +2573,7 @@ port(BIT,0,"in",e.."_i",nil,VPORT_REG),
port(BIT,0,"out",e.."_load_o",nil,VPORT_REG)};
t.acklen=1;
t.read_code={va(vi("rddata_reg",t.offset),e.."_i")};
t.write_code={va(vi("rddata_reg",t.offset),vundefined()),
t.write_code={
va(e.."_load_o",1)};
t.extra_code={va(e.."_o",vi("wrdata_reg",t.offset))};
t.ackgen_code_pre={va(e.."_load_o",0)};
......@@ -2470,11 +2590,10 @@ t.signals={signal(BIT,0,e.."_int"),
signal(BIT,0,e.."_sync0"),
signal(BIT,0,e.."_sync1")};
t.acklen=4;
t.write_code={va(e.."_int",vi("wrdata_reg",t.offset)),
va(vi("rddata_reg",t.offset),vundefined())};
t.write_code={va(e.."_int",vi("wrdata_reg",t.offset))};
t.read_code={va(vi("rddata_reg",t.offset),e.."_int")};
t.reset_code_main={va(e.."_int",0)};
t.extra_code={vcomment("synchronizer chain for field : "..t.name.." (type RW/RO, bus_clock_int <-> "..t.clock..")");
t.extra_code={vcomment("synchronizer chain for field : "..t.name.." (type RW/RO, clk_sys_i <-> "..t.clock..")");
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(e.."_o",0);
......@@ -2493,10 +2612,10 @@ t.ports={port(BIT,0,"in",e.."_i","Port for asynchronous (clock: "..t.clock..") B
t.signals={signal(BIT,0,e.."_sync0"),
signal(BIT,0,e.."_sync1")};
t.acklen=1;
t.write_code={va(vi("rddata_reg",t.offset),vundefined())};
t.write_code={};
t.read_code={va(vi("rddata_reg",t.offset),e.."_sync1")};
t.reset_code_main={};
t.extra_code={vcomment("synchronizer chain for field : "..t.name.." (type RO/WO, "..t.clock.." -> bus_clock_int)");
t.extra_code={vcomment("synchronizer chain for field : "..t.name.." (type RO/WO, "..t.clock.." -> clk_sys_i)");
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(e.."_sync0",0);
......@@ -2526,17 +2645,18 @@ signal(BIT,0,e.."_lw_s1"),
signal(BIT,0,e.."_lw_s2"),
signal(BIT,0,e.."_rwsel")};
t.acklen=6;
t.write_code={va(vi("rddata_reg",t.offset),vundefined());
t.write_code={
va(e.."_int_write",vi("wrdata_reg",t.offset));
va(e.."_lw",1);
va(e.."_lw_delay",1);
va(e.."_lw_read_in_progress",0);
va(e.."_rwsel",1);};
t.read_code={va(vi("rddata_reg",t.offset),vundefined());
t.read_code={vif(vequal("wb_we_i",0),{
va(vi("rddata_reg",t.offset),vundefined());
va(e.."_lw",1);
va(e.."_lw_delay",1);
va(e.."_lw_read_in_progress",1);
va(e.."_rwsel",0);};
va(e.."_rwsel",0);});};
t.reset_code_main={va(e.."_lw",0);
va(e.."_lw_delay",0);
va(e.."_lw_read_in_progress",0);
......@@ -2550,7 +2670,7 @@ va(vi("rddata_reg",t.offset),e.."_int_read");
va(e.."_lw_read_in_progress",0);
});
};
t.extra_code={vcomment("asynchronous BIT register : "..t.name.." (type RW/WO, "..t.clock.." <-> bus_clock_int)");
t.extra_code={vcomment("asynchronous BIT register : "..t.name.." (type RW/WO, "..t.clock.." <-> clk_sys_i)");
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(e.."_lw_s0",0);
......@@ -2646,7 +2766,7 @@ va(e.."_swb",0);
va(e.."_swb_delay",0);};
t.ackgen_code_pre={va(e.."_swb",e.."_swb_delay");
va(e.."_swb_delay",0);};
t.extra_code={vcomment("asynchronous "..fieldtype_2_vhdl[t.type].." register : "..t.name.." (type RW/RO, "..t.clock.." <-> bus_clock_int)");
t.extra_code={vcomment("asynchronous "..fieldtype_2_vhdl[t.type].." register : "..t.name.." (type RW/RO, "..t.clock.." <-> clk_sys_i)");
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(e.."_swb_s0",0);
......@@ -2676,9 +2796,10 @@ signal(BIT,0,e.."_lwb_s1"),
signal(BIT,0,e.."_lwb_s2")};
t.acklen=6;
t.write_code={};
t.read_code={va(e.."_lwb",1);
t.read_code={vif(vequal("wb_we_i",0),{
va(e.."_lwb",1);
va(e.."_lwb_delay",1);
va(e.."_lwb_in_progress",1);};
va(e.."_lwb_in_progress",1);});};
t.reset_code_main={va(e.."_lwb",0);
va(e.."_lwb_delay",0);
va(e.."_lwb_in_progress",0);};
......@@ -2689,7 +2810,7 @@ va(vir("rddata_reg",t),e.."_int");
va(e.."_lwb_in_progress",0);
});
};
t.extra_code={vcomment("asynchronous "..fieldtype_2_vhdl[t.type].." register : "..t.name.." (type RO/WO, "..t.clock.." <-> bus_clock_int)"),
t.extra_code={vcomment("asynchronous "..fieldtype_2_vhdl[t.type].." register : "..t.name.." (type RO/WO, "..t.clock.." <-> clk_sys_i)"),
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(e.."_lwb_s0",0);
......@@ -2730,10 +2851,12 @@ va(e.."_lw",1);
va(e.."_lw_delay",1);
va(e.."_lw_read_in_progress",0);
va(e.."_rwsel",1);};
t.read_code={va(e.."_lw",1);
t.read_code={vif(vequal("wb_we_i",0),{
va(e.."_lw",1);
va(e.."_lw_delay",1);
va(e.."_lw_read_in_progress",1);
va(e.."_rwsel",0);};
va(e.."_rwsel",0);});
};
t.reset_code_main={va(e.."_lw",0);
va(e.."_lw_delay",0);
va(e.."_lw_read_in_progress",0);
......@@ -2747,7 +2870,7 @@ va(vir("rddata_reg",t),e.."_int_read");
va(e.."_lw_read_in_progress",0);
});
};
t.extra_code={vcomment("asynchronous "..fieldtype_2_vhdl[t.type].." register : "..t.name.." (type RW/WO, "..t.clock.." <-> bus_clock_int)");
t.extra_code={vcomment("asynchronous "..fieldtype_2_vhdl[t.type].." register : "..t.name.." (type RW/WO, "..t.clock.." <-> clk_sys_i)");
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(e.."_lw_s0",0);
......@@ -2836,27 +2959,27 @@ e.ports={};
e.acklen=1;
e.read_code={va(vir("rddata_reg",e),e.value);};
end
function fill_unused_bits(i,e)
function fill_unused_bits(o,e)
local a={};
local t={};
local o=true;
local i=true;
foreach_subfield(e,function(e,t)
if(e.type==SLV or e.type==SIGNED or e.type==UNSIGNED or e.type==CONSTANT)then
for e=e.offset,(e.offset+e.size-1)do a[e]=1;end
elseif(e.type==BIT or e.type==MONOSTABLE)then
a[e.offset]=1;
end
if(e.access_bus~=WRITE_ONLY)then o=false;end
if(e.access_bus~=WRITE_ONLY)then i=false;end
end);
if(o)then
if(i)then
for e=0,DATA_BUS_WIDTH-1 do
table_join(t,{va(vi(i,e),vundefined());});
table_join(t,{va(vi(o,e),vundefined());});
end
return t;
end
for e=0,DATA_BUS_WIDTH-1 do
if(a[e]==nil)then
table_join(t,{va(vi(i,e),vundefined());});
table_join(t,{va(vi(o,e),vundefined());});
end
end
return t;
......@@ -2891,7 +3014,7 @@ end
if(e.__type==TYPE_RAM)then
gen_code_ram(e);
else
foreach_subfield(e,function(e,t)gen_hdl_code_reg_field(e,t);end);
foreach_subfield(e,function(t,e)gen_hdl_code_reg_field(t,e);end);
end
end
function gen_hdl_block_select_bits()
......@@ -2958,8 +3081,8 @@ e.signals={};
e.maps={};
e.ports={port(SLV,e.addr_bits-e.wrap_bits,"in",t.."_addr_i","Ports for RAM: "..e.name)};
e.reset_code_main={};
table_join(e.maps,{vpm("clk_a_i","bus_clock_int");
vpm("clk_b_i",csel(e.clock~=nil,e.clock,"bus_clock_int"));
table_join(e.maps,{vpm("clk_a_i","clk_sys_i");
vpm("clk_b_i",csel(e.clock~=nil,e.clock,"clk_sys_i"));
vpm("addr_b_i",t.."_addr_i");
vpm("addr_a_i",vi("rwaddr_reg",log2up(e.size)-1,0));
});
......@@ -3012,7 +3135,7 @@ signal(BIT,0,"eic_ier_write_int");};
["extra_code"]={va(vi("eic_ier_int",periph.irqcount-1,0),vi("wrdata_reg",periph.irqcount-1,0));};
["no_std_regbank"]=true;
};
local n={["__type"]=TYPE_REG;
local s={["__type"]=TYPE_REG;
["__blockindex"]=1000002;
["align"]=1;
["name"]="Interrupt status register";
......@@ -3031,7 +3154,7 @@ signal(BIT,0,"eic_isr_write_int");};
["extra_code"]={va(vi("eic_isr_clear_int",periph.irqcount-1,0),vi("wrdata_reg",periph.irqcount-1,0));};
["no_std_regbank"]=true;
};
local s={["__type"]=TYPE_REG;
local n={["__type"]=TYPE_REG;
["__blockindex"]=1000003;
["align"]=1;
["name"]="Interrupt mask register";
......@@ -3048,7 +3171,7 @@ e.index=t;
t=t+1;
table.insert(o,{["index"]=e.index;["trigger"]=e.trigger;});
fix_prefix(e);
local o={
local t={
["__blockindex"]=e.index;
["__type"]=TYPE_FIELD;
["type"]=BIT;
......@@ -3059,7 +3182,7 @@ local o={
["access_bus"]=READ_WRITE;
["access_dev"]=READ_WRITE;
};
local r={
local o={
["__blockindex"]=e.index;
["__type"]=TYPE_FIELD;
["type"]=BIT;
......@@ -3070,7 +3193,7 @@ local r={
["access_bus"]=WRITE_ONLY;
["access_dev"]=READ_ONLY;
};
local h={
local r={
["__blockindex"]=e.index;
["__type"]=TYPE_FIELD;
["type"]=BIT;
......@@ -3081,7 +3204,7 @@ local h={
["access_bus"]=WRITE_ONLY;
["access_dev"]=READ_ONLY;
};
local t={
local h={
["__blockindex"]=e.index;
["__type"]=TYPE_FIELD;
["type"]=BIT;
......@@ -3101,20 +3224,20 @@ end
if(e.mask_line==true)then
table_join(e.ports,{port(BIT,0,"out",e.full_prefix.."_mask_o");});
end
table.insert(a,h);
table.insert(n,o);
table.insert(a,r);
table.insert(s,t);
table.insert(i,r);
table.insert(n,h);
table.insert(i,o);
end);
add_global_signals({
signal(SLV,periph.irqcount,"irq_inputs_vector_int");
});
table.insert(periph,a);
table.insert(periph,i);
table.insert(periph,s);
table.insert(periph,n);
table.insert(periph,s);
local e={vgm("g_num_interrupts",periph.irqcount);
vpm("clk_i","bus_clock_int");
vpm("clk_i","clk_sys_i");
vpm("rst_n_i","rst_n_i");
vpm("irq_i","irq_inputs_vector_int");
vpm("irq_ack_o","eic_irq_ack_int");
......@@ -3126,7 +3249,7 @@ vpm("reg_idr_wr_stb_i","eic_idr_write_int");
vpm("reg_isr_o","eic_isr_status_int");
vpm("reg_isr_i","eic_isr_clear_int");
vpm("reg_isr_wr_stb_i","eic_isr_write_int");
vpm("wb_irq_o","wb_irq_o");
vpm("wb_irq_o","wb_int_o");
};
local a;
for o,t in ipairs(o)do
......@@ -3276,7 +3399,7 @@ table_join(t.ackgen_code,{va(e.full_prefix.."_wrreq_int",0)});
table_join(t.reset_code_main,{va(e.full_prefix.."_wrreq_int",0)});
else
local t=o[0];
table_join(t.extra_code,{vsyncprocess("bus_clock_int","rst_n_i",{
table_join(t.extra_code,{vsyncprocess("clk_sys_i","rst_n_i",{
vreset(0,{
va(e.full_prefix.."_rdreq_int_d0",0)
});
......@@ -3302,44 +3425,58 @@ va(vi("ack_sreg",0),1);
};
t.dont_emit_ack_code=true;
end
local n={
local s={
["__type"]=TYPE_REG;
["name"]="FIFO '"..e.name.."' control/status register";
["c_prefix"]=e.c_prefix.."_CSR";
["hdl_prefix"]=e.hdl_prefix.."_CSR";
["no_std_regbank"]=true;
};
function gen_fifo_csr_field(h,a,r,o,s,i,t)
function gen_fifo_csr_field(d,n,t,r,h,o,a,i)
print("GenCSR Field "..t);
if(e.flags_bus==nil)then
return;
end
if inset(h,e.flags_bus)then
if inset(d,e.flags_bus)then
local t={
["__type"]=TYPE_FIELD;
["name"]=r;
["description"]=o;
["name"]=t;
["description"]=r;
["access_bus"]=READ_ONLY;
["access_dev"]=WRITE_ONLY;
["type"]=i;
["size"]=s;
["offset"]=t;
["c_prefix"]=a;
["hdl_prefix"]=a;
["type"]=o;
["size"]=h;
["offset"]=a;
["c_prefix"]=n;
["hdl_prefix"]=n;
["signals"]={};
["read_code"]={};
["ack_len"]=2;
};
local o=e.full_prefix.."_"..a.."_int";
table_join(e.maps,{vpm(e.nrdwr.."_"..a.."_o",o)});
table_join(t.signals,{signal(i,s,o)});
if(i==BIT)then
table_join(t.read_code,{va(vi("rddata_reg",t.offset),o)});
local a=e.full_prefix.."_"..n.."_int";
if(i==nil)then
i=true
else
table_join(t.read_code,{va(vi("rddata_reg",t.offset+t.size-1,t.offset),o)});
i=false
end
table.insert(n,t);
else
table_join(e.maps,{vpm(e.nrdwr.."_"..a.."_o",vopenpin())});
if(i)then
table_join(e.maps,{vpm(e.nrdwr.."_"..n.."_o",a)});
end
table_join(t.signals,{signal(csel(o==MONOSTABLE,BIT,o),h,a)});
if(o==BIT)then
table_join(t.read_code,{va(vi("rddata_reg",t.offset),a)});
elseif(o==SLV)then
table_join(t.read_code,{va(vi("rddata_reg",t.offset+t.size-1,t.offset),a)});
elseif(o==MONOSTABLE)then
t.access_bus=WRITE_ONLY;
t.access_dev=READ_ONLY;
t.reset_code_main={va(a,0)};
t.write_code={vif(vequal(vi("rddata_reg",t.offset),1),{va(a,1)})};
t.ackgen_code={va(a,0)}
end
table.insert(s,t);
elseif(i)then
table_join(e.maps,{vpm(e.nrdwr.."_"..n.."_o",vopenpin())});
end
end
gen_fifo_csr_field(FIFO_FULL,
......@@ -3356,6 +3493,14 @@ gen_fifo_csr_field(FIFO_EMPTY,
1,
BIT,
17);
gen_fifo_csr_field(FIFO_CLEAR,
"clear_bus",
"FIFO clear",
"write 1: clears FIFO '"..e.name.."\nwrite 0: no effect",
1,
MONOSTABLE,
18,
false);
gen_fifo_csr_field(FIFO_COUNT,
"usedw",
"FIFO counter",
......@@ -3364,10 +3509,38 @@ e.usedw_size,
SLV,
0);
if(type(e.flags_bus)=="table")then
table.insert(periph,n);
table.insert(periph,s);
end
table_join(e.maps,{vpm(e.nrdwr.."_req_i",e.full_prefix.."_"..e.nrdwr.."req_int")});
end
function fifo_wire_clear_ports(e)
c_dev=inset(FIFO_CLEAR,e.flags_dev);
c_bus=inset(FIFO_CLEAR,e.flags_bus);
table_join(e.signals,{
signal(BIT,0,e.full_prefix.."_rst_n")
});
table_join(e.maps,{vpm("rst_n_i",e.full_prefix.."_rst_n")});
if(c_dev)then
table_join(e.ports,{port(BIT,0,"in",e.full_prefix.."_clear_i","FIFO clear")});
end
if(c_dev and c_bus)then
table_join(e.extra_code,{
va(e.full_prefix.."_rst_n",vand("rst_n_i",vnot(vor(e.full_prefix.."_clear_i",e.full_prefix.."_clear_bus_int"))));
});
elseif(c_dev)then
table_join(e.extra_code,{
va(e.full_prefix.."_rst_n",vand("rst_n_i",vnot(e.full_prefix.."_clear_i")));
});
elseif(c_bus)then
table_join(e.extra_code,{
va(e.full_prefix.."_rst_n",vand("rst_n_i",vnot(e.full_prefix.."_clear_bus_int")));
});
else
table_join(e.extra_code,{
va(e.full_prefix.."_rst_n","rst_n_i");
});
end
end
function gen_code_fifo(e)
local t=string.lower(periph.hdl_prefix.."_"..e.hdl_prefix);
dbg("GenCodeFIFO");
......@@ -3385,9 +3558,11 @@ e.nrdwr="rd";
end
fifo_wire_core_ports(e);
fifo_wire_bus_ports(e);
fifo_wire_clear_ports(e);
table_join(e.signals,{
signal(SLV,e.total_size,e.full_prefix.."_in_int"),
signal(SLV,e.total_size,e.full_prefix.."_out_int")});
signal(SLV,e.total_size,e.full_prefix.."_out_int")
});
if(e.direction==BUS_TO_CORE)then
table_join(e.signals,{signal(BIT,0,e.full_prefix.."_wrreq_int")});
else
......@@ -3395,14 +3570,14 @@ table_join(e.signals,{signal(BIT,0,e.full_prefix.."_rdreq_int")});
table_join(e.signals,{signal(BIT,0,e.full_prefix.."_rdreq_int_d0")});
end
if(e.clock==nil)then
table_join(e.maps,{vpm("clk_i","bus_clock_int");});
table_join(e.maps,{vpm("clk_i","clk_sys_i");});
else
if(e.direction==BUS_TO_CORE)then
table_join(e.maps,{vpm("rd_clk_i",e.clock);
vpm("wr_clk_i","bus_clock_int")});
vpm("wr_clk_i","clk_sys_i")});
elseif(e.direction==CORE_TO_BUS)then
table_join(e.maps,{vpm("wr_clk_i",e.clock);
vpm("rd_clk_i","bus_clock_int")});
vpm("rd_clk_i","clk_sys_i")});
end
end
table_join(e.maps,{
......@@ -3417,29 +3592,34 @@ vinstance(e.full_prefix.."_INST",csel(e.clock==nil,"wbgen2_fifo_sync","wbgen2_fi
});
end
MAX_ACK_LENGTH=10;
function gen_wishbone_ports()
MODE_CLASSIC=1
MODE_PIPELINED=2
function gen_pipelined_wb_ports(t)
local e={
port(BIT,0,"in","rst_n_i","",VPORT_WB),
port(BIT,0,"in","wb_clk_i","",VPORT_WB),
port(BIT,0,"in","clk_sys_i","",VPORT_WB),
};
if(address_bus_width>0)then
table_join(e,{port(SLV,address_bus_width,"in","wb_addr_i","",VPORT_WB)});
table_join(e,{port(SLV,address_bus_width,"in","wb_adr_i","",VPORT_WB)})
end
table_join(e,{
port(SLV,DATA_BUS_WIDTH,"in","wb_data_i","",VPORT_WB),
port(SLV,DATA_BUS_WIDTH,"out","wb_data_o","",VPORT_WB),
port(SLV,DATA_BUS_WIDTH,"in","wb_dat_i","",VPORT_WB),
port(SLV,DATA_BUS_WIDTH,"out","wb_dat_o","",VPORT_WB),
port(BIT,0,"in","wb_cyc_i","",VPORT_WB),
port(SLV,math.floor((DATA_BUS_WIDTH+7)/8),"in","wb_sel_i","",VPORT_WB),
port(BIT,0,"in","wb_stb_i","",VPORT_WB),
port(BIT,0,"in","wb_we_i","",VPORT_WB),
port(BIT,0,"out","wb_ack_o","",VPORT_WB)
});
if(t==MODE_PIPELINED)then
table_join(e,{port(BIT,0,"out","wb_stall_o","",VPORT_WB)});
end
if(periph.irqcount>0)then
table_join(e,{port(BIT,0,"out","wb_irq_o","",VPORT_WB);});
table_join(e,{port(BIT,0,"out","wb_int_o","",VPORT_WB);});
end
add_global_ports(e);
end
function gen_wishbone_signals()
function gen_pipelined_wb_signals(e)
local e=math.max(1,address_bus_width);
local e={signal(SLV,MAX_ACK_LENGTH,"ack_sreg"),
signal(SLV,DATA_BUS_WIDTH,"rddata_reg"),
......@@ -3449,53 +3629,52 @@ signal(SLV,e,"rwaddr_reg"),
signal(BIT,0,"ack_in_progress"),
signal(BIT,0,"wr_int"),
signal(BIT,0,"rd_int"),
signal(BIT,0,"bus_clock_int"),
signal(SLV,DATA_BUS_WIDTH,"allones"),
signal(SLV,DATA_BUS_WIDTH,"allzeros")
};
add_global_signals(e);
end
function gen_bus_logic_wishbone()
local e;
gen_wishbone_ports();
gen_wishbone_signals();
function gen_bus_logic_pipelined_wb(e)
local t;
gen_pipelined_wb_ports(e);
gen_pipelined_wb_signals(e);
foreach_reg(ALL_REG_TYPES,function(e)
gen_abstract_code(e);
end);
local i={};
local o={};
local i={};
local n={};
foreach_field(function(e,t)
table_join(i,e.reset_code_main);
table_join(o,e.reset_code_main);
end);
foreach_reg(ALL_REG_TYPES,function(e)
table_join(i,e.reset_code_main);
table_join(o,e.reset_code_main);
end);
foreach_reg({TYPE_REG},function(e)
foreach_subfield(e,function(e,t)
table_join(o,e.ackgen_code);
table_join(i,e.ackgen_code);
table_join(n,e.ackgen_code_pre);
end);
table_join(o,e.ackgen_code);
table_join(i,e.ackgen_code);
table_join(n,e.ackgen_code_pre);
end);
local e={};
foreach_reg({TYPE_REG},function(t)
local n=find_max(t,"acklen");
local o={};
local a={};
foreach_subfield(t,function(e,t)table_join(a,e.write_code);end);
foreach_subfield(t,function(e,t)table_join(o,e.read_code);end);
local o={};
foreach_subfield(t,function(e,t)table_join(o,e.write_code);end);
foreach_subfield(t,function(e,t)table_join(a,e.read_code);end);
local i=fill_unused_bits("rddata_reg",t);
table_join(a,t.write_code);
table_join(o,t.read_code);
table_join(o,t.write_code);
table_join(a,t.read_code);
local a={
vif(vequal("wb_we_i",1),{
a,
},{
o,
});
a,
i
});};
};
if(not(t.dont_emit_ack_code==true))then
table_join(a,{va(vi("ack_sreg",math.max(n-1,0)),1);});
table_join(a,{va("ack_in_progress",1);});
......@@ -3541,28 +3720,27 @@ end
e={vif(vand(vequal("wb_cyc_i",1),vequal("wb_stb_i",1)),{e});};
local e={
vcomment("Some internal signals assignments. For (foreseen) compatibility with other bus standards.");
va("wrdata_reg","wb_data_i");
va("wrdata_reg","wb_dat_i");
va("bwsel_reg","wb_sel_i");
va("bus_clock_int","wb_clk_i");
va("rd_int",vand("wb_cyc_i",vand("wb_stb_i",vnot("wb_we_i"))));
va("wr_int",vand("wb_cyc_i",vand("wb_stb_i","wb_we_i")));
va("allones",vothers(1));
va("allzeros",vothers(0));
vcomment("");
vcomment("Main register bank access process.");
vsyncprocess("bus_clock_int","rst_n_i",{
vsyncprocess("clk_sys_i","rst_n_i",{
vreset(0,{
va("ack_sreg",0);
va("ack_in_progress",0);
va("rddata_reg",0);
i
o
});
vposedge({
vcomment("advance the ACK generator shift register");
va(vi("ack_sreg",MAX_ACK_LENGTH-2,0),vi("ack_sreg",MAX_ACK_LENGTH-1,1));
va(vi("ack_sreg",MAX_ACK_LENGTH-1),0);
vif(vequal("ack_in_progress",1),{
vif(vequal(vi("ack_sreg",0),1),{o;va("ack_in_progress",0);},n);
vif(vequal(vi("ack_sreg",0),1),{i;va("ack_in_progress",0);},n);
},{
e
});
......@@ -3577,20 +3755,20 @@ local o={vswitch(vi("rwaddr_reg",address_bus_width-1,address_bus_width-address_b
local o={vcomment("Data output multiplexer process");vcombprocess(a,o);};
foreach_reg({TYPE_RAM},function(e)
table.insert(a,e.full_prefix.."_rddata_int");
local a={va(vi("wb_data_o",e.width-1,0),e.full_prefix.."_rddata_int");};
local a={va(vi("wb_dat_o",e.width-1,0),e.full_prefix.."_rddata_int");};
if(e.width<DATA_BUS_WIDTH)then
table_join(a,{va(vi("wb_data_o",DATA_BUS_WIDTH-1,e.width),0);});
table_join(a,{va(vi("wb_dat_o",DATA_BUS_WIDTH-1,e.width),0);});
end
table_join(t,{vcase(e.select_bits,a);});
end);
table.insert(a,"wb_addr_i");
table_join(t,{vcasedefault(va("wb_data_o","rddata_reg"));});
table.insert(a,"wb_adr_i");
table_join(t,{vcasedefault(va("wb_dat_o","rddata_reg"));});
table_join(e,o);
end
local a={"wb_addr_i","rd_int","wr_int"};
local a={"wb_adr_i","rd_int","wr_int"};
local t={};
foreach_reg({TYPE_RAM},function(e)
table_join(t,{vif(vequal(vi("wb_addr_i",address_bus_width-1,address_bus_width-address_bus_select_bits),e.select_bits),{
table_join(t,{vif(vequal(vi("wb_adr_i",address_bus_width-1,address_bus_width-address_bus_select_bits),e.select_bits),{
va(e.full_prefix.."_rd_int","rd_int");
va(e.full_prefix.."_wr_int","wr_int");
},{
......@@ -3600,7 +3778,7 @@ va(e.full_prefix.."_rd_int",0);
end);
table_join(e,{vcomment("Read & write lines decoder for RAMs");vcombprocess(a,t);});
else
table_join(e,{vcomment("Drive the data output bus");va("wb_data_o","rddata_reg")});
table_join(e,{vcomment("Drive the data output bus");va("wb_dat_o","rddata_reg")});
end
foreach_reg(ALL_REG_TYPES,function(t)
if(t.extra_code~=nil)then
......@@ -3614,10 +3792,11 @@ end
end);
end);
if(address_bus_width>0)then
table_join(e,{va("rwaddr_reg","wb_addr_i");});
table_join(e,{va("rwaddr_reg","wb_adr_i");});
else
table_join(e,{va("rwaddr_reg",vothers(0));});
end
table_join(e,{va("wb_stall_o",vand(vnot(vi("ack_sreg",0)),vand("wb_stb_i","wb_cyc_i")))});
table_join(e,{vcomment("ACK signal generation. Just pass the LSB of ACK counter.");
va("wb_ack_o",vi("ack_sreg",0));
});
......@@ -3631,12 +3810,14 @@ options.register_data_output=false;
options.lang="vhdl";
options.c_reg_style="struct";
options.hdl_reg_style="signals";
options.doc_format="html"
require"alt_getopt"
local e=[[slave Wishbone generator
wbgen2 [options] input_file.wb]]
local t=[[options:
-C, --co=FILE Write the slave's generated C header file to FILE
-D, --doco=FILE Write the slave's generated HTML documentation to FILE
-f, --docformat=FORMAT Write documentation for texinfo or HTML (defaults to HTML)
-D, --doco=FILE Write the slave's generated documentation to FILE
-h, --help Show this help text
-l, --lang=LANG Set the output Hardware Description Language (HDL) to LANG
Valid values for LANG: {vhdl,verilog}
......@@ -3650,7 +3831,7 @@ local t=[[options:
-p, --vpo=FILE Generate a VHDL package for slave's generated VHDL
(necessary with --hstyle=record)
wbgen2 (c) Tomasz Wlostowski/CERN BE-CO-HT 2010]]
wbgen2 (c) Tomasz Wlostowski/CERN BE-CO-HT 2010-2012]]
function usage()
print(e)
print("Try `wbgen2 -h' for more information")
......@@ -3659,11 +3840,12 @@ function usage_complete()
print(e)
print(t)
end
function parse_args(o)
function parse_args(a)
local t={
help="h",
version="v",
co="C",
docformat="f",
doco="D",
constco="K",
lang="l",
......@@ -3673,8 +3855,8 @@ cstyle="s",
hstyle="H"
}
local e
local a
e,a=alt_getopt.get_opts(o,"hvC:D:K:l:V:s:H:p:",t)
local o
e,o=alt_getopt.get_opts(a,"hvC:D:K:l:V:s:f:H:p:",t)
for t,e in pairs(e)do
if t=="h"then
usage_complete()
......@@ -3688,6 +3870,8 @@ elseif t=="D"then
options.output_doc_file=e
elseif t=="K"then
options.output_vlog_constants_file=e
elseif t=="f"then
options.doc_format=e
elseif t=="l"then
options.lang=e
if(options.lang~="vhdl"and options.lang~="verilog")then
......@@ -3709,18 +3893,21 @@ end
options.hdl_reg_style=e
end
end
if(o[a]==nil)then
if(a[o]==nil)then
usage()
os.exit(0)
end
input_wb_file=o[a];
input_wb_file=a[o];
end
parse_args(arg);
dofile(input_wb_file);
if(periph==nil)then die("missing peripheral declaration");end
foreach_field(fix_prefix);
foreach_field(fix_access);
foreach_field(check_field_types);
foreach_reg(ALL_REG_TYPES,fix_prefix);
foreach_reg(ALL_REG_TYPES,check_obj_names_prefixes);
foreach_field(check_obj_names_prefixes);
periph=fix_prefix(periph);
wbgen_count_subblocks();
wbgen_generate_eic();
......@@ -3737,7 +3924,7 @@ foreach_reg({TYPE_FIFO},gen_code_fifo);
foreach_field(calc_num_fields);
foreach_reg({TYPE_REG,TYPE_RAM,TYPE_FIFO},calc_address_sizes);
assign_addresses();
tree=gen_bus_logic_wishbone();
tree=gen_bus_logic_pipelined_wb(MODE_PIPELINED);
cgen_build_signals_ports();
if(options.output_hdl_file~=nil)then
if(options.lang=="vhdl")then
......@@ -3755,6 +3942,10 @@ cgen_gen_vlog_constants(options.output_vlog_constants_file);
end
if(options.output_doc_file~=nil)then
cgen_generate_init(options.output_doc_file);
cgen_generate_documentation();
if(options.doc_format=="html")then
cgen_generate_html_documentation();
else
cgen_generate_texinfo_documentation();
end
cgen_generate_done();
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment