Commit de40961e authored by twlostow's avatar twlostow

added support for wrapping VHDL registers fields in a RECORD

git-svn-id: http://svn.ohwr.org/wishbone-gen@24 4537843c-45c2-4d80-8546-c3283569414f
parent a281a99c
......@@ -198,21 +198,37 @@ function signal(type, nbits, name, comment)
return t;
end
VPORT_WB = 1;
VPORT_REG = 2;
-- constructor for a HDL port
function port(type, nbits, dir, name, comment, is_wb)
function port(type, nbits, dir, name, comment, extra_flags)
local t = {}
t.comment = comment;
t.type = type;
if(t.type == SLV and nbits == 1) then
t.type = BIT;
end
t.range= nbits;
t.name = name;
t.dir = dir;
if(is_wb ~= nil and is_wb) then
t.is_wb = true;
else
t.is_wb = false;
if(extra_flags ~= nil) then
if(extra_flags == VPORT_WB) then
t.is_wb = true;
t.is_reg_port = false;
elseif(extra_flags == VPORT_REG) then
t.is_wb = false;
t.is_reg_port = true;
else
t.is_wb =false
t.is_reg_port = false;
end
end
return t;
end
......
......@@ -36,15 +36,92 @@ function gen_vhdl_bin_literal(value, numbits)
r=r/2;
end
return str..'\"';
end
function strip_periph_prefix(s)
return string.gsub(s, "^"..periph.hdl_prefix.."\_", "")
end
-- fixme: do this neatly
function port2record(s)
if(options.hdl_reg_style ~= "record") then
return s
end
for i,port in ipairs(g_portlist) do
if(port.name == s and port.is_reg_port) then
return "regs_b."..strip_periph_prefix(s)
end
end
return s
end
function cgen_vhdl_package()
emit("package "..periph.hdl_prefix.."_wbgen2_pkg is")
indent_right();
emit("type t_"..periph.hdl_prefix.."_registers is record");
indent_right();
local p_list= {};
for i=1,table.getn(g_portlist) do
local port = g_portlist[i];
if(port.is_reg_port == true) then
table.insert(p_list, port);
end
end
for i,port in ipairs(p_list) do
local line = string.format("%-40s : %s", strip_periph_prefix(port.name), fieldtype_2_vhdl[port.type]);
if(port.range > 1) then
line = line.."("..(port.range-1).." downto 0)";
end
line = line..";";
emit(line);
end
emit("end record;");
indent_left();
emit("");
emit("constant c_"..periph.hdl_prefix.."_registers_init_value: t_"..periph.hdl_prefix.."_registers := (");
indent_right();
for i=1,table.getn(p_list) do
local port = p_list[i];
line = strip_periph_prefix(port.name).." => ";
if(port.range > 1) then
line = line.."(others => 'Z')"
else
line = line.."'Z'"
end
if(i ~= table.getn(p_list)) then
line = line..",";
end
emit(line);
end
indent_left();
emit(");");
indent_left();
indent_left();
emit("end package;");
end
-- function generates a VHDL file header (some comments and library/package include definitions).
function cgen_vhdl_header()
function cgen_vhdl_header(file_name)
emit("---------------------------------------------------------------------------------------");
emit("-- Title : Wishbone slave core for "..periph.name);
emit("---------------------------------------------------------------------------------------");
emit("-- File : "..options.output_hdl_file);
emit("-- File : "..file_name);
emit("-- Author : auto-generated by wbgen2 from "..input_wb_file);
emit("-- Created : "..os.date());
emit("-- Standard : VHDL'87");
......@@ -59,8 +136,8 @@ function cgen_vhdl_header()
-- do we have RAMs or FIFOs? - if yes, include the wbgen2 components library.
if(periph.ramcount > 0 or periph.fifocount > 0 or periph.irqcount > 0) then
emit("library wbgen2;");
emit("use wbgen2.wbgen2_pkg.all;");
-- emit("library wbgen2;");
emit("use work.wbgen2_pkg.all;");
end
emit("");
......@@ -71,6 +148,11 @@ end
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");
indent_right();
emit ("port (");
......@@ -80,28 +162,31 @@ function cgen_vhdl_entity()
for i=1,table.getn(g_portlist) do
local port = g_portlist[i];
-- check if this port is the last one, so we won't put a semicolon after it's definition
if(i == table.getn(g_portlist)) then last = true; else last = false; end
if(options.hdl_reg_style == "signals" or not port.is_reg_port) 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
emitx("-- "..port.comment.."\n");
end
-- generate code for the port
local line = string.format("%-40s : %-6s %s", port.name, port.dir, fieldtype_2_vhdl[port.type]);
-- 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
emitx("-- "..port.comment.."\n");
end
-- generate code for the port
local line = string.format("%-40s : %-6s %s", port.name, port.dir, fieldtype_2_vhdl[port.type]);
if(port.range > 1) then
line = line.."("..(port.range-1).." downto 0)";
end
if(port.range > 1) then
line = line.."("..(port.range-1).." downto 0)";
end
-- eventually append a semicolon
line=line..csel(last, "", ";");
-- eventually append a semicolon
line=line..csel((i == table.getn(g_portlist)) and not (options.hdl_reg_style == "record"), "", ";");
-- and spit out the line
-- and spit out the line
emit(line);
end
end
if(options.hdl_reg_style == "record") then
emit(string.format("%-40s : %-6s %s", "regs_b", "inout", "t_"..periph.hdl_prefix.."_registers"));
end
indent_left();
emit(");");
......@@ -123,11 +208,15 @@ function cgen_vhdl_entity()
s=s..";";
emit(s);
end
emit("");
emit("begin");
indent_right();
if(options.hdl_reg_style == "record") then
emit("regs_b <= c_"..periph.hdl_prefix.."_registers_init_value;");
end
end
-- function generates the ending of VHDL file - in our case an END statement, closing the single ARCHITECTURE block.
......@@ -309,19 +398,21 @@ function cgen_generate_vhdl_code(tree)
-- generates the signal name with subrange (if applies): signame, signame(h downto l) or signame(h).
function gen_subrange(t)
local n = port2record(t.name);
-- node is a VHDL "open" pin declaration?
if(type(t.node) == "table" and t.node.t == "openpin") then
return "open";
end
if(type(t.node) == "table" and t.node.t == "openpin") then
return "open";
end
--print("gensub: ", t.name);
if (t.h ~= nil and ( t.l == nil or (t.l == t.h))) then
return t.name.."("..t.h..")";
return n.."("..t.h..")";
elseif(t.h ~= nil and t.l ~= nil) then
return t.name.."("..t.h.." downto "..t.l..")";
return n.."("..t.h.." downto "..t.l..")";
else
return t.name;
return n;
end
end
......@@ -638,12 +729,24 @@ function cgen_generate_vhdl_code(tree)
func(v);
end
end
end
end
if(options.hdl_reg_style == "record" and options.output_package_file ~= nil) then
cgen_generate_init(options.output_package_file);
cgen_new_snippet();
cgen_vhdl_header(options.output_package_file);
cgen_vhdl_package();
cgen_write_current_snippet();
cgen_generate_done();
end
cgen_generate_init(options.output_hdl_file)
-- here we go. Let's create a new snippet of code. VHDL generator is single-pass, so we'll need only one snippet.
cgen_new_snippet();
-- output the header,
cgen_vhdl_header();
cgen_vhdl_header(options.output_hdl_file);
-- .. the entity declaration
cgen_vhdl_entity();
-- the main code
......@@ -654,6 +757,7 @@ function cgen_generate_vhdl_code(tree)
-- and flush the snippet to the output file :)
cgen_write_current_snippet();
cgen_generate_done();
-- voila, we're done!
end
This diff is collapsed.
......@@ -5,26 +5,26 @@ MAX_ACK_LENGTH = 10;
function gen_wishbone_ports()
local ports = {
port(BIT, 0, "in", "rst_n_i", "", true),
port(BIT, 0, "in", "wb_clk_i", "", true),
port(BIT, 0, "in", "rst_n_i", "", VPORT_WB),
port(BIT, 0, "in", "wb_clk_i", "", VPORT_WB),
};
if(address_bus_width > 0 ) then
table_join(ports, { port(SLV, address_bus_width, "in", "wb_addr_i", "", true) });
table_join(ports, { port(SLV, address_bus_width, "in", "wb_addr_i", "", VPORT_WB) });
end
table_join(ports, {
port(SLV, DATA_BUS_WIDTH, "in", "wb_data_i", "", true),
port(SLV, DATA_BUS_WIDTH, "out", "wb_data_o", "", true),
port(BIT, 0, "in", "wb_cyc_i", "", true),
port(SLV, math.floor((DATA_BUS_WIDTH+7)/8), "in", "wb_sel_i", "", true),
port(BIT, 0, "in", "wb_stb_i", "", true),
port(BIT, 0, "in", "wb_we_i", "", true),
port(BIT, 0, "out", "wb_ack_o", "", true)
port(SLV, DATA_BUS_WIDTH, "in", "wb_data_i", "", VPORT_WB),
port(SLV, DATA_BUS_WIDTH, "out", "wb_data_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(periph.irqcount > 0) then
table_join(ports, { port(BIT, 0, "out" ,"wb_irq_o", "", true); });
table_join(ports, { port(BIT, 0, "out" ,"wb_irq_o", "", VPORT_WB); });
end
......
This diff is collapsed.
......@@ -9,7 +9,7 @@ function fifo_wire_core_ports(fifo)
local ports = {
port(BIT, 0, "in", prefix.."_"..fifo.rdwr.."_req_i",
csel(fifo.direction == BUS_TO_CORE, "FIFO read request", "FIFO write request" ))
csel(fifo.direction == BUS_TO_CORE, "FIFO read request", "FIFO write request" ), VPORT_REG)
};
-- wire the read/write request port
......@@ -17,18 +17,18 @@ function fifo_wire_core_ports(fifo)
-- add full/empty/usedw ports
if inset(FIFO_FULL, fifo.flags_dev) then
table_join(ports, { port (BIT, 0, "out", prefix.."_"..fifo.rdwr.."_full_o", "FIFO full flag") });
table_join(ports, { port (BIT, 0, "out", prefix.."_"..fifo.rdwr.."_full_o", "FIFO full flag", VPORT_REG) });
table_join(fifo.maps, { vpm (fifo.rdwr.."_full_o", prefix.."_"..fifo.rdwr.."_full_o")});
end
if inset(FIFO_EMPTY, fifo.flags_dev) then
table_join(ports, { port (BIT, 0, "out", prefix.."_"..fifo.rdwr.."_empty_o", "FIFO empty flag") });
table_join(ports, { port (BIT, 0, "out", prefix.."_"..fifo.rdwr.."_empty_o", "FIFO empty flag", VPORT_REG) });
table_join(fifo.maps, { vpm (fifo.rdwr.."_empty_o", prefix.."_"..fifo.rdwr.."_empty_o")});
end
if inset(FIFO_COUNT, fifo.flags_dev) then
table_join(ports, { port (SLV, fifo.usedw_size, "out", prefix.."_"..fifo.rdwr.."_usedw_o",
"FIFO number of used words") });
"FIFO number of used words", VPORT_REG) });
table_join(fifo.maps, { vpm (fifo.rdwr.."_usedw_o", prefix.."_"..fifo.rdwr.."_usedw_o")});
end
......@@ -39,7 +39,7 @@ function fifo_wire_core_ports(fifo)
if(fifo.direction == BUS_TO_CORE) then -- bus -> core fifo
-- generate an output port for the field
table_join(ports, {port (field.type, field.size, "out", field_pfx.."_o")});
table_join(ports, {port (field.type, field.size, "out", field_pfx.."_o", "", VPORT_REG)});
-- assign the output to the FIFO output port
table_join(fifo.extra_code, {
va(field_pfx.."_o",
......@@ -48,8 +48,8 @@ function fifo_wire_core_ports(fifo)
else
-- generate an input port for the field
table_join(ports, {port (field.type, field.size, "in", field_pfx.."_i")});
table_join(ports, {port (field.type, field.size, "in", field_pfx.."_i", "", VPORT_REG)});
-- core -> bus fifo: wire the inputs to FIFO data input
table_join(fifo.extra_code, {
va(
......
......@@ -26,6 +26,7 @@ options.target_interconnect = "wb-classic";
options.register_data_output = false;
options.lang = "vhdl";
options.c_reg_style = "struct";
options.hdl_reg_style = "signals";
require "alt_getopt"
......@@ -40,9 +41,13 @@ local commands_string = [[options:
Valid values for LANG: {vhdl,verilog}
-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}
-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
-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]]
......@@ -65,12 +70,15 @@ function parse_args(arg)
constco = "K",
lang = "l",
vo = "V",
cstyle = "s"
vpo = "p",
cstyle = "s",
hstyle = "H"
}
local optarg
local optind
optarg,optind = alt_getopt.get_opts (arg, "hvC:D:K:l:V:s:", long_opts)
optarg,optind = alt_getopt.get_opts (arg, "hvC:D:K:l:V:s:H:p:", long_opts)
for key,value in pairs (optarg) do
if key == "h" then
usage_complete()
......@@ -103,7 +111,15 @@ function parse_args(arg)
elseif key == "V" then
options.output_hdl_file = value
end
elseif key == "p" then
options.output_package_file = value
elseif key == "H" then
if (value ~= "signals" and value ~= "record") then
die("Unknown register style: "..value);
end
options.hdl_reg_style = value
end
end
if(arg[optind] == nil) then
......@@ -161,14 +177,11 @@ tree=gen_bus_logic_wishbone();
cgen_build_signals_ports();
if(options.output_hdl_file ~= nil) then
cgen_generate_init(options.output_hdl_file)
if (options.lang == "vhdl") then
cgen_generate_vhdl_code(tree);
elseif (options.lang == "verilog") then
cgen_generate_verilog_code(tree);
end
cgen_generate_done();
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
......
This diff is collapsed.
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