Commit 6ee9c2e0 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

final updates to wbgen2 before it gets replaced by Cheby:

- record_full interface option: use general cores's library WB interface types
  to simplify connection of the cores. Enabled by -H record_full option
- use byte addressing for WB address (in record_full mode)
- allow specifying package name with record/component definitions (hdl_package field in the peripheral record)
- fixed indentation & formatting of produced VHDL package files
- include VHDL component declaration in the package files
parent cc5a5c00
......@@ -217,6 +217,7 @@ end
VPORT_WB = 1;
VPORT_REG = 2;
VPORT_CLK_RST = 3;
-- constructor for a HDL port
function port(type, nbits, dir, name, comment, extra_flags)
......@@ -237,9 +238,15 @@ function port(type, nbits, dir, name, comment, extra_flags)
if(extra_flags == VPORT_WB) then
t.is_wb = true;
t.is_reg_port = false;
t.is_clk_rst = false;
elseif(extra_flags == VPORT_REG) then
t.is_wb = false;
t.is_reg_port = true;
t.is_clk_rst = false;
elseif(extra_flags == VPORT_CLK_RST) then
t.is_wb = false;
t.is_reg_port = false;
t.is_clk_rst = true;
else
t.is_wb =false
t.is_reg_port = false;
......
......@@ -18,6 +18,14 @@ fieldtype_2_vhdl[ENUM] = "std_logic_vector";
fieldtype_2_vhdl[SLV] = "std_logic_vector";
function get_pkg_name()
if (periph.hdl_package) then
return periph.hdl_package
else
return periph.hdl_prefix.."_wbgen2_pkg";
end
end
-- generates a string containing VHDL-compatible numeric constant of value [value] and size [numbits]
function gen_vhdl_bin_literal(value, numbits)
if(numbits == 1) then
......@@ -50,9 +58,16 @@ function strip_periph_prefix(s)
return string.gsub(s, "^"..periph.hdl_prefix.."\_", "")
end
function strip_wb_prefix(s)
local t = string.gsub(s, "^wb\_", "")
t = string.gsub(t, "_o$","")
t = string.gsub(t, "_i$","")
return t
end
-- fixme: do this neatly
function port2record(s)
if(options.hdl_reg_style ~= "record") then
if(options.hdl_reg_style == "signals") then
return s
end
......@@ -60,14 +75,23 @@ function port2record(s)
if(port.name == s and port.is_reg_port) then
return csel(port.dir=="in", "regs_i.", "regs_o.")..strip_periph_prefix(s)
end
if(port.name == s and port.is_wb and options.hdl_reg_style == "record_full") then
if s == "wb_int_o" then
return "int_o";
end
return csel(port.dir=="in", "slave_i.", "slave_o.")..strip_wb_prefix(s)
end
end
return s
end
function cgen_vhdl_package()
local pkg_name = periph.hdl_prefix.."_wbgen2_pkg";
emit("package "..pkg_name.." is")
emit("package "..get_pkg_name().." is")
indent_right();
emit("");
......@@ -84,50 +108,68 @@ function cgen_vhdl_package()
cgen_vhdl_port_struct("out");
indent_left();
local typename = "t_"..periph.hdl_prefix.."_in_registers";
emit("");
emit("function \"or\" (left, right: "..typename..") return "..typename..";");
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;");
emit("");
cgen_vhdl_interface_declaration("component")
indent_left();
indent_left();
emit("end package;");
emit("");
emit("package body "..pkg_name.." is");
emit("package body "..get_pkg_name().." is");
indent_right();
emit("function f_x_to_zero (x:std_logic) return std_logic is");
emit("begin")
indent_right();
emit("if x = '1' then")
indent_right();
emit("return '1';")
indent_left();
emit("else")
indent_right();
emit("return '0';")
indent_left();
emit("end if;")
indent_left();
emit("end function;");
emit("")
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);");
indent_right();
emit("variable tmp: std_logic_vector(x'length-1 downto 0);");
indent_left();
emit("begin");
indent_right();
emit("for i in 0 to x'length-1 loop");
indent_right();
emit("if(x(i) = 'X' or x(i) = 'U') then");
indent_right();
emit("tmp(i):= '0';");
indent_left();
emit("else");
indent_right();
emit("tmp(i):=x(i);");
indent_left();
emit("end if; ");
indent_left();
emit("end loop; ");
emit("return tmp;");
indent_left();
emit("end function;");
emit("");
emit("function \"or\" (left, right: "..typename..") return "..typename.." is");
indent_right();
emit("variable tmp: "..typename..";");
indent_left();
emit("begin");
indent_right();
for i=1,table.getn(g_portlist) do
local port = g_portlist[i];
......@@ -137,8 +179,10 @@ function cgen_vhdl_package()
end
end
emit("return tmp;");
indent_left();
emit("end function;");
indent_left();
emit("");
emit("end package body;");
end
......@@ -168,8 +212,8 @@ function cgen_vhdl_port_struct(direction)
emit(line);
end
emit("end record;");
indent_left();
emit("end record;");
emit("");
emit("constant c_"..periph.hdl_prefix.."_"..direction.."_registers_init_value: t_"..periph.hdl_prefix.."_"..direction.."_registers := (");
indent_right();
......@@ -188,7 +232,8 @@ function cgen_vhdl_port_struct(direction)
emit(line);
end
emit(");");
indent_left();
emit(");");
end
......@@ -219,20 +264,15 @@ function cgen_vhdl_header(file_name)
emit("use work.wbgen2_pkg.all;");
end
if(options.hdl_reg_style == "record_full") then
emit("use work.wishbone_pkg.all;");
end
emit("");
end
-- function generates VHDL entity header (ports and generics) and beginning of ARCHITECTURE block (signal and constant definitions).
function cgen_vhdl_entity()
local last;
if(options.hdl_reg_style == "record") then
emit("use work."..periph.hdl_prefix.."_wbgen2_pkg.all;");
emit("\n");
end
emit ("entity "..periph.hdl_entity.." is");
function cgen_vhdl_interface_declaration(keyword)
emit (keyword.." "..periph.hdl_entity.." is");
indent_right();
if(table.getn(g_optlist) ~= 0) then
......@@ -262,7 +302,15 @@ function cgen_vhdl_entity()
for i=1,table.getn(g_portlist) do
local port = g_portlist[i];
if(options.hdl_reg_style == "signals" or not port.is_reg_port) then
local generate = true;
if( options.hdl_reg_style == "record" and port.is_reg_port ) then
generate = false;
elseif ( options.hdl_reg_style == "record_full" and (port.is_reg_port or port.is_wb) ) then
generate = false;
end
if(generate) then
-- if we have a comment associated with current port, let's emit it before the port definition.
if(port.comment ~= nil and port.comment ~= "") then
......@@ -278,24 +326,50 @@ function cgen_vhdl_entity()
end
-- eventually append a semicolon
line=line..csel((i == table.getn(g_portlist)) and not (options.hdl_reg_style == "record"), "", ";");
line=line..csel((i == table.getn(g_portlist)) and not (options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full"), "", ";");
-- and spit out the line
emit(line);
end
end
if(options.hdl_reg_style == "record") then
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"));
if(options.hdl_reg_style == "record_full") then
emit(string.format("%-40s : %-6s %s;", "slave_i", "in", "t_wishbone_slave_in"));
emit(string.format("%-40s : %-6s %s;", "slave_o", "out", "t_wishbone_slave_out"));
emit(string.format("%-40s : %-6s %s;", "int_o", "out", "std_logic"));
end
if(options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full") then
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"));
end
indent_left();
emit(");");
indent_left();
emit("end "..periph.hdl_entity..";");
if ( keyword == "component") then
emit("end component;");
else
emit("end "..periph.hdl_entity..";");
end
emit("");
end
-- function generates VHDL entity header (ports and generics) and beginning of ARCHITECTURE block (signal and constant definitions).
function cgen_vhdl_entity()
local last;
if(options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full") then
emit("use work."..get_pkg_name()..".all;");
emit("\n");
end
cgen_vhdl_interface_declaration("entity")
-- generate the ARCHITECTURE block with signal definitions
emit("architecture syn of "..periph.hdl_entity.." is");
......@@ -853,7 +927,7 @@ function cgen_generate_vhdl_code(tree)
end
end
if(options.hdl_reg_style == "record" and options.output_package_file ~= nil) then
if((options.hdl_reg_style == "record" or options.hdl_reg_style == "record_full") and options.output_package_file ~= nil) then
cgen_generate_init(options.output_package_file);
cgen_new_snippet();
cgen_vhdl_header(options.output_package_file);
......
......@@ -8,8 +8,8 @@ MODE_PIPELINED=2
function gen_pipelined_wb_ports(mode)
local ports = {
port(BIT, 0, "in", "rst_n_i", "", VPORT_WB),
port(BIT, 0, "in", "clk_sys_i", "", VPORT_WB),
port(BIT, 0, "in", "rst_n_i", "", 0),
port(BIT, 0, "in", "clk_sys_i", "", 0),
};
if(address_bus_width > 0 ) then
......@@ -23,7 +23,9 @@ function gen_pipelined_wb_ports(mode)
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)
port(BIT, 0, "out", "wb_ack_o", "", VPORT_WB),
port(BIT, 0, "out", "wb_err_o", "", VPORT_WB),
port(BIT, 0, "out", "wb_rty_o", "", VPORT_WB)
});
if(mode == MODE_PIPELINED) then
......@@ -295,12 +297,19 @@ function gen_bus_logic_pipelined_wb(mode)
if(address_bus_width > 0) then
table_join(code, { va("rwaddr_reg", "wb_adr_i"); });
if(options.hdl_reg_style == "record_full") then
table_join(code, { va("rwaddr_reg", vi("wb_adr_i", address_bus_width + 2 - 1, 2) ); } );
else
table_join(code, { va("rwaddr_reg", "wb_adr_i" ); } );
end
else
table_join(code, { va("rwaddr_reg", vothers(0)); });
end
table_join(code, { va("wb_stall_o", vand(vnot(vi("ack_sreg", 0)), vand("wb_stb_i","wb_cyc_i")))});
table_join(code, { va("wb_err_o", 0 ) } );
table_join(code, { va("wb_rty_o", 0 ) } );
table_join(code, { vcomment("ACK signal generation. Just pass the LSB of ACK counter.");
va("wb_ack_o", vi("ack_sreg", 0));
......
#!/usr/bin/env lua
package.preload['alt_getopt']=(function(...)
local i,s,u,a,o=type,pairs,ipairs,io,os
local n,h,u,o,a=type,pairs,ipairs,io,os
module("alt_getopt")
local function r(e)
local function i(e)
local t=1
local t=#e
local t={}
......@@ -11,19 +11,19 @@ t[e]=#a
end
return t
end
local function d(t,e)
a.stderr:write(t)
o.exit(e)
local function r(e,t)
o.stderr:write(e)
a.exit(t)
end
local function a(e)
d("Unknown option `-"..
r("Unknown option `-"..
(#e>1 and"-"or"")..e.."'\n",1)
end
local function l(t,e)
if not t[e]then
a(e)
end
while i(t[e])=="string"do
while n(t[e])=="string"do
e=t[e]
if not t[e]then
a(e)
......@@ -31,14 +31,14 @@ end
end
return e
end
function get_ordered_opts(n,o,a)
function get_ordered_opts(n,a,d)
local t=1
local e=1
local i={}
local h={}
local o=r(o)
for t,e in s(a)do
o[t]=e
local o={}
local s={}
local i=i(a)
for t,e in h(d)do
i[t]=e
end
while t<=#n do
local a=n[t]
......@@ -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)
t=l(o,t)
if o[t]==0 then
d("Bad usage of option `"..a.."'\n",1)
end
h[e]=a:sub(s+1)
i[e]=t
local h=a:find("=",1,true)
if h then
local t=a:sub(3,h-1)
t=l(i,t)
if i[t]==0 then
r("Bad usage of option `"..a.."'\n",1)
end
s[e]=a:sub(h+1)
o[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(i,h)
if i[h]==0 then
o[e]=h
else
if t==#n then
d("Missed value for option `"..a.."'\n",1)
r("Missed value for option `"..a.."'\n",1)
end
h[e]=n[t+1]
i[e]=s
s[e]=n[t+1]
o[e]=h
t=t+1
end
end
e=e+1
elseif a:sub(1,1)=="-"then
local s
for r=2,a:len()do
local s=l(o,a:sub(r,r))
if o[s]==0 then
i[e]=s
local h
for d=2,a:len()do
local h=l(i,a:sub(d,d))
if i[h]==0 then
o[e]=h
e=e+1
elseif a:len()==r then
elseif a:len()==d then
if t==#n then
d("Missed value for option `-"..s.."'\n",1)
r("Missed value for option `-"..h.."'\n",1)
end
h[e]=n[t+1]
i[e]=s
s[e]=n[t+1]
o[e]=h
t=t+1
e=e+1
break
else
h[e]=a:sub(r+1)
i[e]=s
s[e]=a:sub(d+1)
o[e]=h
e=e+1
break
end
......@@ -100,11 +100,11 @@ break
end
t=t+1
end
return i,t,h
return o,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)
local t,i,o=get_ordered_opts(t,a,o)
for a,t in u(t)do
if o[a]then
e[t]=o[a]
......@@ -191,7 +191,7 @@ t=t+1;
end
return t;
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 or e.type==PASS_THROUGH)then
......@@ -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
......@@ -254,27 +254,27 @@ end
print("Align ",e.name,e.align,o,a);
return a;
end
function calc_field_offset(t,e)
local a=e.current_offset;
if(e.__type==TYPE_FIFO)then
local o=align(t,a);
if((o%DATA_BUS_WIDTH)+t.size>DATA_BUS_WIDTH)then
t.align=DATA_BUS_WIDTH;
a=align(t,a);
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);
else
a=o;
end
e.current_offset=a+t.size;
t.offset=a;
t.current_offset=a+e.size;
e.offset=a;
else
a=align(t,a);
e.current_offset=a+t.size;
t.offset=a;
a=align(e,a);
t.current_offset=a+e.size;
e.offset=a;
end
t.offset_unaligned=e.current_offset_unaligned;
e.current_offset_unaligned=e.current_offset_unaligned+t.size;
if(e.__type==TYPE_REG and e.current_offset>DATA_BUS_WIDTH)then
die("Total size of register '"..e.name.."' ("..e.current_offset..") exceeds data bus width ("..DATA_BUS_WIDTH..")");
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..")");
end
end
function calc_num_fields(t,e)
......@@ -296,11 +296,11 @@ 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,a,t)
if(e)then
function csel(t,a,e)
if(t)then
return a;
else
return t;
return e;
end
end
function check_field_types(e)
......@@ -324,13 +324,13 @@ return e;
end
return e;
end
function default_access(e,t,o,a)
function default_access(e,t,a,o)
if(e.type==t)then
if(e.access_bus==nil)then
e.access_bus=o;
e.access_bus=a;
end
if(e.access_dev==nil)then
e.access_dev=a;
e.access_dev=o;
end
end
end
......@@ -375,9 +375,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
......@@ -404,25 +404,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;
......@@ -432,26 +432,26 @@ table.insert(t,e);
end
end
function tree_2_table(e)
local t={};
foreach_reg({TYPE_REG,TYPE_RAM,TYPE_FIFO,TYPE_IRQ},function(a)
if(a[e]~=nil)then
if(type(a[e])=='table')then
table_join(t,a[e]);
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]);
else
table.insert(t,a[e]);
table.insert(a,t[e]);
end
end
foreach_subfield(a,function(a,o)
if(a[e]~=nil)then
if(type(a[e])=='table')then
table_join(t,a[e]);
foreach_subfield(t,function(t,o)
if(t[e]~=nil)then
if(type(t[e])=='table')then
table_join(a,t[e]);
else
table.insert(t,a[e]);
table.insert(a,t[e]);
end
end
end);
end);
return t;
return a;
end
function remove_duplicates(o)
function count_entries(t,a)
......@@ -470,19 +470,19 @@ end
return e;
end
function wbgen_count_subblocks()
local t=0;
local e=0;
local a=0;
local t=0;
local o=0;
foreach_reg({TYPE_RAM},function(e)t=t+1;end);
foreach_reg({TYPE_REG},function(e)a=a+1;end);
foreach_reg({TYPE_FIFO},function(t)e=e+1;end);
foreach_reg({TYPE_IRQ},function(e)o=o+1;end);
periph.ramcount=t;
periph.fifocount=e;
periph.regcount=a;
periph.irqcount=o;
if(t+e+a+o==0)then
local a=0;
foreach_reg({TYPE_RAM},function(t)e=e+1;end);
foreach_reg({TYPE_REG},function(e)o=o+1;end);
foreach_reg({TYPE_FIFO},function(e)t=t+1;end);
foreach_reg({TYPE_IRQ},function(e)a=a+1;end);
periph.ramcount=e;
periph.fifocount=t;
periph.regcount=o;
periph.irqcount=a;
if(e+t+o+a==0)then
die("Can't generate an empty peripheral. Define some regs, RAMs, FIFOs or IRQs, please...");
end
end
......@@ -503,27 +503,27 @@ return setmetatable(t,getmetatable(e))
end
return a(i)
end
function va(t,a)
function va(a,t)
local e={};
e.t="assign";
e.dst=t;
e.src=a;
e.dst=a;
e.src=t;
return e;
end
function vi(a,o,t)
function vi(t,o,a)
local e={};
e.t="index";
e.name=a;
e.name=t;
e.h=o;
e.l=t;
e.l=a;
return e;
end
function vinstance(o,a,t)
function vinstance(a,t,o)
local e={};
e.t="instance";
e.name=o;
e.component=a;
e.maps=t;
e.name=a;
e.component=t;
e.maps=o;
return e;
end
function vpm(a,t)
......@@ -533,33 +533,33 @@ e.to=a;
e.from=t;
return e;
end
function vgm(t,a)
function vgm(a,t)
local e={};
e.t="genmap";
e.to=t;
e.from=a;
e.to=a;
e.from=t;
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,a,o)
function vsyncprocess(a,o,t)
local e={};
e.t="syncprocess";
e.clk=t;
e.rst=a;
e.code=o;
e.clk=a;
e.rst=o;
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)
......@@ -583,18 +583,18 @@ e.cond={t};
e.code=a;
return e;
end
function vequal(t,a)
function vequal(a,t)
local e={};
e.t="eq";
e.a=t;
e.b=a;
e.a=a;
e.b=t;
return e;
end
function vand(a,t)
function vand(t,a)
local e={};
e.t="and";
e.a=a;
e.b=t;
e.a=t;
e.b=a;
return e;
end
function vor(a,t)
......@@ -610,18 +610,18 @@ e.t="not";
e.a=t;
return e;
end
function vswitch(t,a)
function vswitch(a,t)
local e={};
e.t="switch";
e.a=t;
e.code=a;
e.a=a;
e.code=t;
return e;
end
function vcase(t,a)
function vcase(a,t)
local e={};
e.t="case";
e.a=t;
e.code=a;
e.a=a;
e.code=t;
return e;
end
function vcasedefault(t)
......@@ -636,11 +636,11 @@ e.t="comment";
e.str=t;
return e;
end
function vsub(t,a)
function vsub(a,t)
local e={};
e.t="sub";
e.a=t;
e.b=a;
e.a=a;
e.b=t;
return e;
end
function vothers(t)
......@@ -669,6 +669,7 @@ return e;
end
VPORT_WB=1;
VPORT_REG=2;
VPORT_CLK_RST=3;
function port(a,i,o,s,n,t)
local e={}
e.comment=n;
......@@ -680,9 +681,15 @@ if(t~=nil)then
if(t==VPORT_WB)then
e.is_wb=true;
e.is_reg_port=false;
e.is_clk_rst=false;
elseif(t==VPORT_REG)then
e.is_wb=false;
e.is_reg_port=true;
e.is_clk_rst=false;
elseif(t==VPORT_CLK_RST)then
e.is_wb=false;
e.is_reg_port=false;
e.is_clk_rst=true;
else
e.is_wb=false
e.is_reg_port=false;
......@@ -727,17 +734,17 @@ table_join(e,tree_2_table("ports"));
return e;
end
function cgen_build_optional_list()
local o={}
local a={}
local o={}
local t=1
for i,e in pairs(tree_2_table("optional"))do
if o[e]==nil then
o[e]=1
a[t]=e
if a[e]==nil then
a[e]=1
o[t]=e
t=t+1
end
end
return a
return o
end
function cgen_find_sigport(e)
for a,t in pairs(g_portlist)do if(e==t.name)then return t;end end
......@@ -831,23 +838,30 @@ 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 get_pkg_name()
if(periph.hdl_package)then
return periph.hdl_package
else
return periph.hdl_prefix.."_wbgen2_pkg";
end
end
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
......@@ -856,20 +870,31 @@ end
function strip_periph_prefix(e)
return string.gsub(e,"^"..periph.hdl_prefix.."\_","")
end
function strip_wb_prefix(e)
local e=string.gsub(e,"^wb\_","")
e=string.gsub(e,"_o$","")
e=string.gsub(e,"_i$","")
return e
end
function port2record(e)
if(options.hdl_reg_style~="record")then
if(options.hdl_reg_style=="signals")then
return e
end
for a,t in ipairs(g_portlist)do
if(t.name==e and t.is_reg_port)then
return csel(t.dir=="in","regs_i.","regs_o.")..strip_periph_prefix(e)
end
if(t.name==e and t.is_wb and options.hdl_reg_style=="record_full")then
if e=="wb_int_o"then
return"int_o";
end
return csel(t.dir=="in","slave_i.","slave_o.")..strip_wb_prefix(e)
end
end
return e
end
function cgen_vhdl_package()
local t=periph.hdl_prefix.."_wbgen2_pkg";
emit("package "..t.." is")
emit("package "..get_pkg_name().." is")
indent_right();
emit("");
emit("");
......@@ -880,39 +905,62 @@ 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("");
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();
emit("");
cgen_vhdl_interface_declaration("component")
indent_left();
emit("end package;");
emit("");
emit("package body "..t.." is");
emit("package body "..get_pkg_name().." is");
indent_right();
emit("function f_x_to_zero (x:std_logic) return std_logic is");
emit("begin")
indent_right();
emit("if x = '1' then")
indent_right();
emit("return '1';")
indent_left();
emit("else")
indent_right();
emit("return '0';")
indent_left();
emit("end if;")
indent_left();
emit("end function;");
emit("")
emit("function f_x_to_zero (x:std_logic_vector) return std_logic_vector is");
indent_right();
emit("variable tmp: std_logic_vector(x'length-1 downto 0);");
indent_left();
emit("begin");
indent_right();
emit("for i in 0 to x'length-1 loop");
indent_right();
emit("if(x(i) = 'X' or x(i) = 'U') then");
indent_right();
emit("tmp(i):= '0';");
indent_left();
emit("else");
indent_right();
emit("tmp(i):=x(i);");
indent_left();
emit("end if; ");
indent_left();
emit("end loop; ");
emit("return tmp;");
indent_left();
emit("end function;");
emit("");
emit("function \"or\" (left, right: "..e..") return "..e.." is");
indent_right();
emit("variable tmp: "..e..";");
indent_left();
emit("begin");
indent_right();
for e=1,table.getn(g_portlist)do
local e=g_portlist[e];
if(e.is_reg_port==true and e.dir=="in")then
......@@ -921,20 +969,23 @@ emit("tmp."..e.." := f_x_to_zero(left."..e..") or f_x_to_zero(right."..e..");");
end
end
emit("return tmp;");
indent_left();
emit("end function;");
indent_left();
emit("");
emit("end package body;");
end
function cgen_vhdl_port_struct(a)
emit("type t_"..periph.hdl_prefix.."_"..a.."_registers is record");
function cgen_vhdl_port_struct(o)
emit("type t_"..periph.hdl_prefix.."_"..o.."_registers is record");
indent_right();
local t={};
local a={};
for e=1,table.getn(g_portlist)do
local e=g_portlist[e];
if(e.is_reg_port==true and e.dir==a)then
table.insert(t,e);
if(e.is_reg_port==true and e.dir==o)then
table.insert(a,e);
end
end
for t,e in ipairs(t)do
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
......@@ -943,24 +994,25 @@ end
t=t..";";
emit(t);
end
emit("end record;");
indent_left();
emit("end record;");
emit("");
emit("constant c_"..periph.hdl_prefix.."_"..a.."_registers_init_value: t_"..periph.hdl_prefix.."_"..a.."_registers := (");
emit("constant c_"..periph.hdl_prefix.."_"..o.."_registers_init_value: t_"..periph.hdl_prefix.."_"..o.."_registers := (");
indent_right();
for a=1,table.getn(t)do
local e=t[a];
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(a~=table.getn(t))then
if(t~=table.getn(a))then
line=line..",";
end
emit(line);
end
indent_left();
emit(");");
end
function cgen_vhdl_header(e)
......@@ -985,24 +1037,22 @@ emit("use ieee.numeric_std.all;");
if(periph.ramcount>0 or periph.fifocount>0 or periph.irqcount>0)then
emit("use work.wbgen2_pkg.all;");
end
emit("");
if(options.hdl_reg_style=="record_full")then
emit("use work.wishbone_pkg.all;");
end
function cgen_vhdl_entity()
local e;
if(options.hdl_reg_style=="record")then
emit("use work."..periph.hdl_prefix.."_wbgen2_pkg.all;");
emit("\n");
emit("");
end
emit("entity "..periph.hdl_entity.." is");
function cgen_vhdl_interface_declaration(o)
emit(o.." "..periph.hdl_entity.." is");
indent_right();
if(table.getn(g_optlist)~=0)then
emit("generic (");
indent_right();
emiti()
for t,e in pairs(g_optlist)do
for e,t in pairs(g_optlist)do
emiti();
emitx(e.." : integer := 1");
if(t~=table.getn(g_optlist))then
emitx(t.." : integer := 1");
if(e~=table.getn(g_optlist))then
emit(";")
else
emit(");")
......@@ -1016,7 +1066,13 @@ emit("port (");
indent_right();
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
local t=true;
if(options.hdl_reg_style=="record"and e.is_reg_port)then
t=false;
elseif(options.hdl_reg_style=="record_full"and(e.is_reg_port or e.is_wb))then
t=false;
end
if(t)then
if(e.comment~=nil and e.comment~="")then
emitx("-- "..e.comment.."\n");
end
......@@ -1024,19 +1080,36 @@ local t=string.format("%-40s : %-6s %s",e.name,e.dir,fieldtype_2_vhdl[e.type]);
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"),"",";");
t=t..csel((a==table.getn(g_portlist))and not(options.hdl_reg_style=="record"or options.hdl_reg_style=="record_full"),"",";");
emit(t);
end
end
if(options.hdl_reg_style=="record")then
emit(string.format("%-40s : %-6s %s","regs_i","in","t_"..periph.hdl_prefix.."_in_registers;"));
if(options.hdl_reg_style=="record_full")then
emit(string.format("%-40s : %-6s %s;","slave_i","in","t_wishbone_slave_in"));
emit(string.format("%-40s : %-6s %s;","slave_o","out","t_wishbone_slave_out"));
emit(string.format("%-40s : %-6s %s;","int_o","out","std_logic"));
end
if(options.hdl_reg_style=="record"or options.hdl_reg_style=="record_full")then
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"));
end
indent_left();
emit(");");
indent_left();
if(o=="component")then
emit("end component;");
else
emit("end "..periph.hdl_entity..";");
end
emit("");
end
function cgen_vhdl_entity()
local e;
if(options.hdl_reg_style=="record"or options.hdl_reg_style=="record_full")then
emit("use work."..get_pkg_name()..".all;");
emit("\n");
end
cgen_vhdl_interface_declaration("entity")
emit("architecture syn of "..periph.hdl_entity.." is");
emit("");
for t,e in pairs(g_siglist)do
......@@ -1223,16 +1296,16 @@ else
die("unsupported assignment: "..t.name.." "..e.name);end
else die("unsupported assignment: "..t.name.." "..e.name);end
end
function cgen_vhdl_assign(t)
local e=node_typesize(t.dst);
local t=node_typesize(t.src);
if(t.type==EXPRESSION)then
function cgen_vhdl_assign(e)
local t=node_typesize(e.dst);
local e=node_typesize(e.src);
if(e.type==EXPRESSION)then
emiti();
emitx(gen_subrange(e).." <= ");
recurse({t.code});
emitx(gen_subrange(t).." <= ");
recurse({e.code});
emitx(";\n");
else
emit(gen_subrange(e).." <= "..gen_vhdl_typecvt(e,t)..";");
emit(gen_subrange(t).." <= "..gen_vhdl_typecvt(t,e)..";");
end
end
function cgen_vhdl_if(e)
......@@ -1262,13 +1335,13 @@ emitx(") generate\n");
indent_right();recurse(e.code);indent_left();
emit("end generate "..gname..";");
end
function cgen_vhdl_not(t)
local e=node_typesize(t.a);
function cgen_vhdl_not(e)
local t=node_typesize(e.a);
emitx("not ");
if(e.type==EXPRESSION)then
emitx("(");recurse({t.a});emitx(")");
if(t.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
else
emitx(gen_subrange(e));
emitx(gen_subrange(t));
end
end
function cgen_vhdl_binary_op(t)
......@@ -1321,25 +1394,25 @@ end
emit("end case;");
end
function cgen_vhdl_instance(t)
local o=0;
local a=0;
local o=0;
local e;
emit(t.name.." : "..t.component);
for t,e in pairs(t.maps)do
if(e.t=="genmap")then
a=a+1;
elseif(e.t=="portmap")then
o=o+1;
elseif(e.t=="portmap")then
a=a+1;
end
end
if(a>0)then
if(o>0)then
indent_right();
emit("generic map (");
indent_right();
e=1;
for o,t in pairs(t.maps)do
for a,t in pairs(t.maps)do
if(t.t=="genmap")then
emit(string.format("%-20s => %s",t.to,t.from)..csel(e==a,"",","));
emit(string.format("%-20s => %s",t.to,t.from)..csel(e==o,"",","));
e=e+1;
end
end
......@@ -1347,15 +1420,15 @@ indent_left();
emit(")");
indent_left();
end
if(o>0)then
if(a>0)then
indent_right();
emit("port map (");
indent_right();
e=1;
for a,t in pairs(t.maps)do
for o,t in pairs(t.maps)do
if(t.t=="portmap")then
local a=node_typesize(t.from);
emit(string.format("%-20s => %s",t.to,gen_subrange(a))..csel(e==o,"",","));
local o=node_typesize(t.from);
emit(string.format("%-20s => %s",t.to,gen_subrange(o))..csel(e==a,"",","));
e=e+1;
end
end
......@@ -1402,7 +1475,7 @@ t(e);
end
end
end
if(options.hdl_reg_style=="record"and options.output_package_file~=nil)then
if((options.hdl_reg_style=="record"or options.hdl_reg_style=="record_full")and options.output_package_file~=nil)then
cgen_generate_init(options.output_package_file);
cgen_new_snippet();
cgen_vhdl_header(options.output_package_file);
......@@ -1491,7 +1564,7 @@ function cgen_verilog_ending()
indent_left();
emit("endmodule");
end
function cgen_generate_verilog_code(n)
function cgen_generate_verilog_code(i)
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
......@@ -1647,22 +1720,22 @@ else
emitx(gen_subrange(t));
end
end
function cgen_verilog_binary_op(e)
local o=node_typesize(e.a);
local a=node_typesize(e.b);
local t=e.t;
function cgen_verilog_binary_op(t)
local o=node_typesize(t.a);
local a=node_typesize(t.b);
local e=t.t;
if(o.type==EXPRESSION)then
emitx("(");recurse({e.a});emitx(")");
emitx("(");recurse({t.a});emitx(")");
else
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(e=="eq")then emitx(" == ");end
if(e=="and")then emitx(" && ");end
if(e=="or")then emitx(" || ");end
if(e=="sub")then emitx(" - ");end
if(e=="add")then emitx(" + ");end
if(a.type==EXPRESSION)then
emitx("(");recurse({e.b});emitx(")");
emitx("(");recurse({t.b});emitx(")");
else
emitx(gen_subrange(a));
end
......@@ -1696,29 +1769,29 @@ end
end
emit("endcase");
end
function cgen_verilog_instance(a)
function cgen_verilog_instance(t)
local a=0;
local o=0;
local i=0;
local e;
emitx(a.component.." ");
for t,e in pairs(a.maps)do
emitx(t.component.." ");
for t,e in pairs(t.maps)do
if(e.t=="genmap")then
i=i+1;
elseif(e.t=="portmap")then
o=o+1;
elseif(e.t=="portmap")then
a=a+1;
end
end
if(i>0)then
if(o>0)then
indent_right();
emit("# (");
indent_right();
e=1;
for t,a in pairs(a.maps)do
for t,a in pairs(t.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==i,"",","));
emit(string.format(".%-20s(%s)",a.to,t)..csel(e==o,"",","));
e=e+1;
end
end
......@@ -1726,15 +1799,15 @@ indent_left();
emit(")");
indent_left();
end
if(o>0)then
if(a>0)then
indent_right();
emit(a.name.." ( ");
emit(t.name.." ( ");
indent_right();
e=1;
for a,t in pairs(a.maps)do
for o,t in pairs(t.maps)do
if(t.t=="portmap")then
local a=node_typesize(t.from);
emit(string.format(".%-20s(%s)",t.to,gen_subrange(a))..csel(e==o,"",","));
local o=node_typesize(t.from);
emit(string.format(".%-20s(%s)",t.to,gen_subrange(o))..csel(e==a,"",","));
e=e+1;
end
end
......@@ -1803,7 +1876,7 @@ cgen_new_snippet();
cgen_verilog_header();
local a=cgen_get_snippet();
cgen_new_snippet();
recurse(n);
recurse(i);
cgen_verilog_ending();
local e=cgen_get_snippet();
cgen_new_snippet();
......@@ -2002,15 +2075,15 @@ end
function htable_trstyle(e,a,t)
tbl.data[e].style=t;
end
function htable_frame(o,a,e,t)
function htable_frame(a,e,o,t)
if(t==nil)then
o.data[a][e].extra='style="border: solid 1px black;"';
a.data[e][o].extra='style="border: solid 1px black;"';
else
o.data[a][e].extra='style="border-left: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
o.data[a][t].extra='style="border-right: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
if(t>e+1)then
for e=e+1,t-1 do
o.data[a][e].extra='border-top: solid 1px black; border-bottom: solid 1px black;';
a.data[e][o].extra='style="border-left: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
a.data[e][t].extra='style="border-right: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;';
if(t>o+1)then
for t=o+1,t-1 do
a.data[e][t].extra='border-top: solid 1px black; border-bottom: solid 1px black;';
end
end
end
......@@ -2048,45 +2121,45 @@ emit("</tr>");
end
emit("</table>");
end
function has_any_ports(e)
local t=false;
if(e.ports~=nil)then return true;end
foreach_subfield(e,function(e)if(e.ports~=nil)then t=true;end end);
return t;
function has_any_ports(t)
local e=false;
if(t.ports~=nil)then return true;end
foreach_subfield(t,function(t)if(t.ports~=nil)then e=true;end end);
return e;
end
function htable_add_row(e,t)
if(t>e.rows)then
for t=e.rows+1,t do
function htable_add_row(e,a)
if(a>e.rows)then
for t=e.rows+1,a do
e.data[t]={};
for a=1,e.cols do
e.data[t][a]={};
e.data[t][a].text="";
end
end
e.rows=t;
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(e,t)
return'<a name="'..e..'">'..t..'</a>';
function hanchor(t,e)
return'<a name="'..t..'">'..e..'</a>';
end
doc_toc={};
function hsection(t,a,o)
function hsection(a,t,o)
local e={};
local i=0;
e.id_mangled="sect_"..t.."_"..a;
e.key=t*1e3+a;
if(a~=0)then
e.id_mangled="sect_"..a.."_"..t;
e.key=a*1e3+t;
if(t~=0)then
e.level=2;
e.id=t.."."..a..".";
e.id=a.."."..t..".";
else
e.level=1;
e.id=t..".";
e.id=a..".";
end
e.name=o;
table.insert(doc_toc,e);
......@@ -2135,9 +2208,9 @@ end
end);
cgen_doc_symbol(t);
end
function cgen_doc_mem_symbol(e)
function cgen_doc_mem_symbol(a)
local t={};
for e,a in pairs(e.ports)do
for e,a in pairs(a.ports)do
local e=a;
if(string.find(a.name,"_i")~=nil)then
e.is_wb=true;
......@@ -2146,33 +2219,33 @@ e.is_wb=false;
end
table.insert(t,e);
end
if(e.clock~=nil)then
local e=port(BIT,0,"in",e.clock);
if(a.clock~=nil)then
local e=port(BIT,0,"in",a.clock);
e.is_wb=true;
table.insert(t,e);
end
cgen_doc_symbol(t);
end
function cgen_doc_symbol(i)
function cgen_doc_symbol(o)
local t=htable_new(3,5);
local a=1;
local e=1;
local o=true;
for o,e in pairs(i)do
local i=true;
for o,e in pairs(o)do
if(e.is_wb)then
htable_add_row(t,a);
cgen_doc_port(t.data[a],e,true);
a=a+1;
end
end
for i,a in ipairs(i)do
for o,a in ipairs(o)do
if(type(a)=="string")then
if(o==false)then
if(i==false)then
htable_add_row(t,e);
row=t.data[e];row[3].text="&nbsp;";
e=e+1;
else
o=false;
i=false;
end
htable_add_row(t,e);
local t=t.data[e];
......@@ -2212,7 +2285,7 @@ local e=periph.description;
if(e==nil)then e="";end
emit('<p>'..string.gsub(e,"\n","<br>")..'</p>');
emit('<h3>Contents:</h3>');
table.sort(doc_toc,function(t,e)return t.key<e.key;end);
table.sort(doc_toc,function(e,t)return e.key<t.key;end);
for t,e in ipairs(doc_toc)do
emit('<span style="margin-left: '..((e.level-1)*20)..'px; ">'..e.id.." "..hlink('#'..e.id_mangled,e.name)..'</span><br/>');
end
......@@ -2249,19 +2322,19 @@ e[5].text=string.upper(t.c_prefix);
i=not i;
end
end);
foreach_reg({TYPE_RAM},function(e)
if(e.full_hdl_prefix~=nil)then
foreach_reg({TYPE_RAM},function(t)
if(t.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);
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 - 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);
i=not i;
end
end);
......@@ -2274,20 +2347,20 @@ 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;
......@@ -2298,18 +2371,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
......@@ -2409,26 +2482,26 @@ 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_html_documentation()
......@@ -2437,19 +2510,19 @@ 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 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();
......@@ -2459,8 +2532,8 @@ cgen_doc_header_and_toc();
emit(e);
emit(i);
emit(o);
emit(t);
emit(a);
emit(t);
emit('</BODY>');
emit('</HTML>');
cgen_write_current_snippet();
......@@ -2977,163 +3050,163 @@ t.ackgen_code_pre={va(e.."_int",e.."_int_delay");
va(e.."_int_delay",0);};
end
end
function gen_hdl_code_bit(e,a)
local t=gen_hdl_field_prefix(e,a);
e.prefix=t;
if(e.clock==nil)then
if(e.access==ACC_RW_RO)then
e.ports={port(BIT,0,"out",t.."_o","Port for BIT field: '"..e.name.."' in reg: '"..a.name.."'",VPORT_REG)};
e.signals={signal(BIT,0,t.."_int")};
e.acklen=1;
e.write_code={
va(t.."_int",vi("wrdata_reg",e.offset))};
e.read_code={va(vi("rddata_reg",e.offset),t.."_int")};
e.reset_code_main={va(t.."_int",csel(e.reset_value==nil,0,e.reset_value))};
e.extra_code={va(t.."_o",t.."_int")};
elseif(e.access==ACC_RO_WO)then
e.ports={port(BIT,0,"in",t.."_i","Port for BIT field: '"..e.name.."' in reg: '"..a.name.."'",VPORT_REG)};
e.signals={};
e.acklen=1;
e.write_code={};
e.read_code={va(vi("rddata_reg",e.offset),t.."_i")};
e.reset_code_main={};
e.extra_code={};
elseif(e.access==ACC_WO_RO)then
die("WO-RO type unsupported yet ("..e.name..")");
elseif(e.access==ACC_RW_RW)then
if(e.load==LOAD_EXT)then
e.ports={port(BIT,0,"out",t.."_o","Ports for BIT field: '"..e.name.."' in reg: '"..a.name.."'",VPORT_REG),
port(BIT,0,"in",t.."_i",nil,VPORT_REG),
port(BIT,0,"out",t.."_load_o",nil,VPORT_REG)};
e.acklen=1;
e.read_code={va(vi("rddata_reg",e.offset),t.."_i")};
e.write_code={
va(t.."_load_o",1)};
e.extra_code={va(t.."_o",vi("wrdata_reg",e.offset))};
e.ackgen_code_pre={va(t.."_load_o",0)};
e.ackgen_code={va(t.."_load_o",0)};
e.reset_code_main={va(t.."_load_o",0)};
function gen_hdl_code_bit(t,a)
local e=gen_hdl_field_prefix(t,a);
t.prefix=e;
if(t.clock==nil)then
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(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",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={};
t.read_code={va(vi("rddata_reg",t.offset),e.."_i")};
t.reset_code_main={};
t.extra_code={};
elseif(t.access==ACC_WO_RO)then
die("WO-RO type unsupported yet ("..t.name..")");
elseif(t.access==ACC_RW_RW)then
if(t.load==LOAD_EXT)then
t.ports={port(BIT,0,"out",e.."_o","Ports for BIT field: '"..t.name.."' in reg: '"..a.name.."'",VPORT_REG),
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(e.."_load_o",1)};
t.extra_code={va(e.."_o",vi("wrdata_reg",t.offset))};
t.ackgen_code_pre={va(e.."_load_o",0)};
t.ackgen_code={va(e.."_load_o",0)};
t.reset_code_main={va(e.."_load_o",0)};
else
die("internal RW/RW register storage unsupported yet ("..e.name..")");
die("internal RW/RW register storage unsupported yet ("..t.name..")");
end
end
else
if(e.access==ACC_RW_RO)then
e.ports={port(BIT,0,"out",t.."_o","Port for asynchronous (clock: "..e.clock..") BIT field: '"..e.name.."' in reg: '"..a.name.."'",VPORT_REG)};
e.signals={signal(BIT,0,t.."_int"),
signal(BIT,0,t.."_sync0"),
signal(BIT,0,t.."_sync1")};
e.acklen=4;
e.write_code={va(t.."_int",vi("wrdata_reg",e.offset))};
e.read_code={va(vi("rddata_reg",e.offset),t.."_int")};
e.reset_code_main={va(t.."_int",csel(e.reset_value==nil,0,e.reset_value))};
e.extra_code={vcomment("synchronizer chain for field : "..e.name.." (type RW/RO, clk_sys_i <-> "..e.clock..")");
vsyncprocess(e.clock,"rst_n_i",{
if(t.access==ACC_RW_RO)then
t.ports={port(BIT,0,"out",e.."_o","Port for asynchronous (clock: "..t.clock..") BIT field: '"..t.name.."' in reg: '"..a.name.."'",VPORT_REG)};
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))};
t.read_code={va(vi("rddata_reg",t.offset),e.."_int")};
t.reset_code_main={va(e.."_int",csel(t.reset_value==nil,0,t.reset_value))};
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(t.."_o",csel(e.reset_value==nil,0,e.reset_value));
va(t.."_sync0",csel(e.reset_value==nil,0,e.reset_value));
va(t.."_sync1",csel(e.reset_value==nil,0,e.reset_value));
va(e.."_o",csel(t.reset_value==nil,0,t.reset_value));
va(e.."_sync0",csel(t.reset_value==nil,0,t.reset_value));
va(e.."_sync1",csel(t.reset_value==nil,0,t.reset_value));
});
vposedge({
va(t.."_sync0",t.."_int");
va(t.."_sync1",t.."_sync0");
va(t.."_o",t.."_sync1");
va(e.."_sync0",e.."_int");
va(e.."_sync1",e.."_sync0");
va(e.."_o",e.."_sync1");
});
});
};
elseif(e.access==ACC_RO_WO)then
e.ports={port(BIT,0,"in",t.."_i","Port for asynchronous (clock: "..e.clock..") BIT field: '"..e.name.."' in reg: '"..a.name.."'",VPORT_REG)};
e.signals={signal(BIT,0,t.."_sync0"),
signal(BIT,0,t.."_sync1")};
e.acklen=1;
e.write_code={};
e.read_code={va(vi("rddata_reg",e.offset),t.."_sync1")};
e.reset_code_main={};
e.extra_code={vcomment("synchronizer chain for field : "..e.name.." (type RO/WO, "..e.clock.." -> clk_sys_i)");
vsyncprocess(e.clock,"rst_n_i",{
elseif(t.access==ACC_RO_WO)then
t.ports={port(BIT,0,"in",e.."_i","Port for asynchronous (clock: "..t.clock..") BIT field: '"..t.name.."' in reg: '"..a.name.."'",VPORT_REG)};
t.signals={signal(BIT,0,e.."_sync0"),
signal(BIT,0,e.."_sync1")};
t.acklen=1;
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.." -> clk_sys_i)");
vsyncprocess(t.clock,"rst_n_i",{
vreset(0,{
va(t.."_sync0",0);
va(t.."_sync1",0);
va(e.."_sync0",0);
va(e.."_sync1",0);
});
vposedge({
va(t.."_sync0",t.."_i");
va(t.."_sync1",t.."_sync0");
va(e.."_sync0",e.."_i");
va(e.."_sync1",e.."_sync0");
});
});
};
elseif(e.access==ACC_RW_RW)then
if(e.load~=LOAD_EXT)then
elseif(t.access==ACC_RW_RW)then
if(t.load~=LOAD_EXT)then
die("Only external load is supported for RW/RW bit fields");
end
local a="Ports for asynchronous (clock: "..e.clock..") RW/RW BIT field: '"..e.name.."' in reg: '"..a.name.."'";
e.ports={port(BIT,0,"out",t.."_o",a,VPORT_REG),
port(BIT,0,"in",t.."_i",nil,VPORT_REG),
port(BIT,0,"out",t.."_load_o",nil,VPORT_REG)};
e.signals={signal(BIT,0,t.."_int_read"),
signal(BIT,0,t.."_int_write"),
signal(BIT,0,t.."_lw"),
signal(BIT,0,t.."_lw_delay"),
signal(BIT,0,t.."_lw_read_in_progress"),
signal(BIT,0,t.."_lw_s0"),
signal(BIT,0,t.."_lw_s1"),
signal(BIT,0,t.."_lw_s2"),
signal(BIT,0,t.."_rwsel")};
e.acklen=6;
e.write_code={
va(t.."_int_write",vi("wrdata_reg",e.offset));
va(t.."_lw",1);
va(t.."_lw_delay",1);
va(t.."_lw_read_in_progress",0);
va(t.."_rwsel",1);};
e.read_code={vif(vequal("wb_we_i",0),{
va(vi("rddata_reg",e.offset),vundefined());
va(t.."_lw",1);
va(t.."_lw_delay",1);
va(t.."_lw_read_in_progress",1);
va(t.."_rwsel",0);});};
e.reset_code_main={va(t.."_lw",0);
va(t.."_lw_delay",0);
va(t.."_lw_read_in_progress",0);
va(t.."_rwsel",0);
va(t.."_int_write",0);
local a="Ports for asynchronous (clock: "..t.clock..") RW/RW BIT field: '"..t.name.."' in reg: '"..a.name.."'";
t.ports={port(BIT,0,"out",e.."_o",a,VPORT_REG),
port(BIT,0,"in",e.."_i",nil,VPORT_REG),
port(BIT,0,"out",e.."_load_o",nil,VPORT_REG)};
t.signals={signal(BIT,0,e.."_int_read"),
signal(BIT,0,e.."_int_write"),
signal(BIT,0,e.."_lw"),
signal(BIT,0,e.."_lw_delay"),
signal(BIT,0,e.."_lw_read_in_progress"),
signal(BIT,0,e.."_lw_s0"),
signal(BIT,0,e.."_lw_s1"),
signal(BIT,0,e.."_lw_s2"),
signal(BIT,0,e.."_rwsel")};
t.acklen=6;
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={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);});};
t.reset_code_main={va(e.."_lw",0);
va(e.."_lw_delay",0);
va(e.."_lw_read_in_progress",0);
va(e.."_rwsel",0);
va(e.."_int_write",0);
};
e.ackgen_code_pre={va(t.."_lw",t.."_lw_delay");
va(t.."_lw_delay",0);
vif(vand(vequal(vi("ack_sreg",1),1),vequal(t.."_lw_read_in_progress",1)),{
va(vi("rddata_reg",e.offset),t.."_int_read");
va(t.."_lw_read_in_progress",0);
t.ackgen_code_pre={va(e.."_lw",e.."_lw_delay");
va(e.."_lw_delay",0);
vif(vand(vequal(vi("ack_sreg",1),1),vequal(e.."_lw_read_in_progress",1)),{
va(vi("rddata_reg",t.offset),e.."_int_read");
va(e.."_lw_read_in_progress",0);
});
};
e.extra_code={vcomment("asynchronous BIT register : "..e.name.." (type RW/WO, "..e.clock.." <-> clk_sys_i)");
vsyncprocess(e.clock,"rst_n_i",{
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(t.."_lw_s0",0);
va(t.."_lw_s1",0);
va(t.."_lw_s2",0);
va(t.."_int_read",0);
va(t.."_load_o",0);
va(t.."_o",0);
va(e.."_lw_s0",0);
va(e.."_lw_s1",0);
va(e.."_lw_s2",0);
va(e.."_int_read",0);
va(e.."_load_o",0);
va(e.."_o",0);
});
vposedge({
va(t.."_lw_s0",t.."_lw");
va(t.."_lw_s1",t.."_lw_s0");
va(t.."_lw_s2",t.."_lw_s1");
vif(vand(vequal(t.."_lw_s2",0),vequal(t.."_lw_s1",1)),{
vif(vequal(t.."_rwsel",1),{
va(t.."_o",t.."_int_write");
va(t.."_load_o",1);
va(e.."_lw_s0",e.."_lw");
va(e.."_lw_s1",e.."_lw_s0");
va(e.."_lw_s2",e.."_lw_s1");
vif(vand(vequal(e.."_lw_s2",0),vequal(e.."_lw_s1",1)),{
vif(vequal(e.."_rwsel",1),{
va(e.."_o",e.."_int_write");
va(e.."_load_o",1);
},{
va(t.."_load_o",0);
va(t.."_int_read",t.."_i");
va(e.."_load_o",0);
va(e.."_int_read",e.."_i");
});
},{
va(t.."_load_o",0);
va(e.."_load_o",0);
});
});
});
};
elseif(e.access==ACC_WO_RO)then
die("WO-RO type unsupported yet ("..e.name..")");
elseif(t.access==ACC_WO_RO)then
die("WO-RO type unsupported yet ("..t.name..")");
end
end
end
......@@ -3537,7 +3610,7 @@ function wbgen_generate_eic()
if(periph.irqcount==0)then return;end
local t=0;
local s={};
local i={["__type"]=TYPE_REG;
local a={["__type"]=TYPE_REG;
["__blockindex"]=1e6;
["align"]=8;
["name"]="Interrupt disable register";
......@@ -3553,7 +3626,7 @@ signal(BIT,0,"eic_idr_write_int");};
["extra_code"]={va(vi("eic_idr_int",periph.irqcount-1,0),vi("wrdata_reg",periph.irqcount-1,0));};
["no_std_regbank"]=true;
};
local a={["__type"]=TYPE_REG;
local o={["__type"]=TYPE_REG;
["__blockindex"]=1000001;
["align"]=1;
["name"]="Interrupt enable register";
......@@ -3569,7 +3642,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 o={["__type"]=TYPE_REG;
local n={["__type"]=TYPE_REG;
["__blockindex"]=1000002;
["align"]=1;
["name"]="Interrupt status register";
......@@ -3588,7 +3661,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 n={["__type"]=TYPE_REG;
local i={["__type"]=TYPE_REG;
["__blockindex"]=1000003;
["align"]=1;
["name"]="Interrupt mask register";
......@@ -3605,7 +3678,7 @@ e.index=t;
t=t+1;
table.insert(s,{["index"]=e.index;["trigger"]=e.trigger;});
fix_prefix(e);
local s={
local t={
["__blockindex"]=e.index;
["__type"]=TYPE_FIELD;
["type"]=BIT;
......@@ -3616,7 +3689,7 @@ local s={
["access_bus"]=READ_WRITE;
["access_dev"]=READ_WRITE;
};
local t={
local s={
["__blockindex"]=e.index;
["__type"]=TYPE_FIELD;
["type"]=BIT;
......@@ -3658,18 +3731,18 @@ end
if(e.mask_line==true)then
table_join(e.ports,{port(BIT,0,"out",e.full_prefix.."_mask_o");});
end
table.insert(i,h);
table.insert(a,h);
table.insert(n,t);
table.insert(i,r);
table.insert(o,s);
table.insert(n,r);
table.insert(a,t);
end);
add_global_signals({
signal(SLV,periph.irqcount,"irq_inputs_vector_int");
});
table.insert(periph,i);
table.insert(periph,a);
table.insert(periph,n);
table.insert(periph,o);
table.insert(periph,i);
table.insert(periph,n);
local e={vgm("g_num_interrupts",periph.irqcount);
vpm("clk_i","clk_sys_i");
vpm("rst_n_i","rst_n_i");
......@@ -3866,34 +3939,34 @@ local s={
["hdl_prefix"]=e.hdl_prefix.."_CSR";
["no_std_regbank"]=true;
};
function gen_fifo_csr_field(a,i,t,d,h,o,r,n)
function gen_fifo_csr_field(r,n,a,d,h,o,t,i)
if(e.flags_bus==nil)then
return;
end
if inset(a,e.flags_bus)then
if inset(r,e.flags_bus)then
local t={
["__type"]=TYPE_FIELD;
["name"]=t;
["name"]=a;
["description"]=d;
["access_bus"]=READ_ONLY;
["access_dev"]=WRITE_ONLY;
["type"]=o;
["size"]=h;
["offset"]=r;
["c_prefix"]=i;
["hdl_prefix"]=i;
["offset"]=t;
["c_prefix"]=n;
["hdl_prefix"]=n;
["signals"]={};
["read_code"]={};
["ack_len"]=2;
};
local a=e.full_prefix.."_"..i.."_int";
if(n==nil)then
n=true
local a=e.full_prefix.."_"..n.."_int";
if(i==nil)then
i=true
else
n=false
i=false
end
if(n)then
table_join(e.maps,{vpm(e.nrdwr.."_"..i.."_o",a)});
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
......@@ -3909,8 +3982,8 @@ table_join(t.read_code,{va(vi("rddata_reg",t.offset),0)});
t.ackgen_code={va(a,0)}
end
table.insert(s,t);
elseif(n)then
table_join(e.maps,{vpm(e.nrdwr.."_"..i.."_o",vopenpin())});
elseif(i)then
table_join(e.maps,{vpm(e.nrdwr.."_"..n.."_o",vopenpin())});
end
end
gen_fifo_csr_field(FIFO_FULL,
......@@ -4030,8 +4103,8 @@ 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","clk_sys_i","",VPORT_WB),
port(BIT,0,"in","rst_n_i","",0),
port(BIT,0,"in","clk_sys_i","",0),
};
if(address_bus_width>0)then
table_join(e,{port(SLV,address_bus_width,"in","wb_adr_i","",VPORT_WB)})
......@@ -4043,7 +4116,9 @@ 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)
port(BIT,0,"out","wb_ack_o","",VPORT_WB),
port(BIT,0,"out","wb_err_o","",VPORT_WB),
port(BIT,0,"out","wb_rty_o","",VPORT_WB)
});
if(t==MODE_PIPELINED)then
table_join(e,{port(BIT,0,"out","wb_stall_o","",VPORT_WB)});
......@@ -4070,38 +4145,38 @@ gen_pipelined_wb_signals(e);
foreach_reg(ALL_REG_TYPES,function(e)
gen_abstract_code(e);
end);
local o={};
local n={};
local i={};
local o={};
foreach_field(function(e,t)
table_join(n,e.reset_code_main);
table_join(o,e.reset_code_main);
end);
foreach_reg(ALL_REG_TYPES,function(e)
table_join(n,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(i,e.ackgen_code);
table_join(o,e.ackgen_code_pre);
table_join(n,e.ackgen_code);
table_join(i,e.ackgen_code_pre);
end);
table_join(i,e.ackgen_code);
table_join(o,e.ackgen_code_pre);
table_join(n,e.ackgen_code);
table_join(i,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
......@@ -4157,14 +4232,14 @@ vreset(0,{
va("ack_sreg",0);
va("ack_in_progress",0);
va("rddata_reg",0);
n
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),{i;va("ack_in_progress",0);},o);
vif(vequal(vi("ack_sreg",0),1),{n;va("ack_in_progress",0);},i);
},{
e
});
......@@ -4233,11 +4308,17 @@ end
end
end);
if(address_bus_width>0)then
if(options.hdl_reg_style=="record_full")then
table_join(e,{va("rwaddr_reg",vi("wb_adr_i",address_bus_width+2-1,2));});
else
table_join(e,{va("rwaddr_reg","wb_adr_i");});
end
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,{va("wb_err_o",0)});
table_join(e,{va("wb_rty_o",0)});
table_join(e,{vcomment("ACK signal generation. Just pass the LSB of ACK counter.");
va("wb_ack_o",vi("ack_sreg",0));
});
......@@ -4265,7 +4346,7 @@ local t=[[options:
-s, --cstyle=STYLE Set the style of register bank in generated C headers
Valid values for STYLE: {struct, defines}
-H, --hstyle=STYLE Set the style of register signals in generated VHDL/Verilog file
Valid values for STYLE: {signals, record}
Valid values for STYLE: {signals, record, record_full}
-K, --constco=FILE Populate FILE with Verilog output (mainly constants)
-v, --version Show version information
-V, --vo=FILE Write the slave's generated HDL code to FILE
......@@ -4281,7 +4362,7 @@ function usage_complete()
print(e)
print(t)
end
function parse_args(a)
function parse_args(o)
local t={
help="h",
version="v",
......@@ -4296,8 +4377,8 @@ cstyle="s",
hstyle="H"
}
local e
local o
e,o=alt_getopt.get_opts(a,"hvC:D:K:l:V:s:f:H:p:",t)
local a
e,a=alt_getopt.get_opts(o,"hvC:D:K:l:V:s:f:H:p:",t)
for t,e in pairs(e)do
if t=="h"then
usage_complete()
......@@ -4328,17 +4409,17 @@ options.output_hdl_file=e
elseif t=="p"then
options.output_package_file=e
elseif t=="H"then
if(e~="signals"and e~="record")then
if(e~="signals"and e~="record"and e~="record_full")then
die("Unknown register style: "..e);
end
options.hdl_reg_style=e
end
end
if(a[o]==nil)then
if(o[a]==nil)then
usage()
os.exit(0)
end
input_wb_file=a[o];
input_wb_file=o[a];
end
parse_args(arg);
dofile(input_wb_file);
......@@ -4389,6 +4470,7 @@ if(options.output_hdl_file~=nil)then
if(options.lang=="vhdl")then
cgen_generate_vhdl_code(tree);
elseif(options.lang=="verilog")then
cgen_generate_verilog_code(tree);
end
end
if(options.output_c_header_file~=nil)then
......
......@@ -44,7 +44,7 @@ local commands_string = [[options:
-s, --cstyle=STYLE Set the style of register bank in generated C headers
Valid values for STYLE: {struct, defines}
-H, --hstyle=STYLE Set the style of register signals in generated VHDL/Verilog file
Valid values for STYLE: {signals, record}
Valid values for STYLE: {signals, record, record_full}
-K, --constco=FILE Populate FILE with Verilog output (mainly constants)
-v, --version Show version information
-V, --vo=FILE Write the slave's generated HDL code to FILE
......@@ -120,7 +120,7 @@ function parse_args(arg)
elseif key == "p" then
options.output_package_file = value
elseif key == "H" then
if (value ~= "signals" and value ~= "record") then
if (value ~= "signals" and value ~= "record" and value ~= "record_full") then
die("Unknown register style: "..value);
end
options.hdl_reg_style = value
......@@ -209,7 +209,7 @@ if(options.output_hdl_file ~= nil) then
if (options.lang == "vhdl") then
cgen_generate_vhdl_code(tree);
elseif (options.lang == "verilog") then
-- cgen_generate_verilog_code(tree);
cgen_generate_verilog_code(tree);
end
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