Commit 7cc2ac4a authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

new code generator (vlog/vhdl)

parent dee54890
#!/usr/bin/lua
-- wbgen2, (c) 2010 Tomasz Wlostowski
-- CERN BE-Co-HT
-- LICENSED UNDER GPL v2
------------------------------
-- HDL syntax tree constructors
------------------------------
-- assignment: dst <= src;
function va (dst, src)
local s={};
s.t="assign";
s.dst=dst;
s.src=src;
return s;
end
-- index: name(h downto l)
function vi(name, h, l)
local s={};
s.t="index";
s.name=name;
s.h=h;
s.l=l;
return s;
end
-- synchronous process: process(clk, rst) begin {code} end process;
function vsyncprocess(clk, rst, code)
local s={};
s.t="syncprocess";
s.clk=clk;
s.rst=rst;
s.code=code;
return s;
end
-- reset in process
function vreset(level, code)
local s={};
s.t="reset";
s.level=level;
s.code=code;
return s;
end
function vposedge(code)
local s={};
s.t="posedge";
s.code=code;
return s;
end
function vif(cond, code, code_else)
local s={};
s.t="if";
s.cond={ cond };
s.code=code;
s.code_else=code_else;
return s;
end
function vequal(a,b)
local s={};
s.t="eq";
s.a=a;
s.b=b;
return s;
end
function vand(a,b)
local s={};
s.t="and";
s.a=a;
s.b=b;
return s;
end
function vnot(a)
local s={};
s.t="not";
s.a=a;
return s;
end
function vswitch(a, code)
local s={};
s.t="switch";
s.a=a;
s.code=code;
return s;
end
function vcase(a, code)
local s={};
s.t="case";
s.a=a;
s.code=code;
return s;
end
function vcasedefault(code)
local s={};
s.t="casedefault";
s.code=code;
return s;
end
function vcomment(str)
local s={};
s.t="comment";
s.str=str;
return s;
end
function vsub(a,b)
local s={};
s.t="sub";
s.a=a;
s.b=b;
return s;
end
-- constructor for a HDL signal
function signal(type, nbits, name, comment)
local t = {}
t.comment = comment;
t.type = type;
t.range= nbits;
t.name = name;
return t;
end
-- constructor for a HDL port
function port(type, nbits, dir, name, comment)
local t = {}
t.comment = comment;
t.type = type;
t.range= nbits;
t.name = name;
t.dir = dir;
return t;
end
function cgen_build_wishbone_ports()
local ports = {
port(BIT, 0, "in", "rst_n_i"),
port(BIT, 0, "in", "wb_clk_i"),
};
if(address_bus_width > 0 ) then
table_join(ports, { port(SLV, address_bus_width, "in", "wb_addr_i") });
end
table_join(ports, {
port(SLV, DATA_BUS_WIDTH, "in", "wb_data_i"),
port(SLV, DATA_BUS_WIDTH, "out", "wb_data_o"),
port(BIT, 0, "in", "wb_cyc_i"),
port(BIT, 0, "in", "wb_sel_i"),
port(BIT, 0, "in", "wb_stb_i"),
port(BIT, 0, "in", "wb_we_i"),
port(BIT, 0, "out", "wb_ack_o")
});
return ports;
end
function cgen_build_clock_list()
local allclocks = tree_2_table("clock");
local i,v;
local clockports = {};
remove_duplicates(allclocks);
for i,v in pairs(allclocks) do
table.insert(clockports, port(BIT, 0, "in", v));
end
return clockports;
end
function cgen_build_siglist()
local siglist = {};
local i,v;
local s;
siglist = tree_2_table("signals");
wb_sigs = { signal(BIT, 0, "wb_ack_regbank"),
signal(UNSIGNED, 4, "ack_cntr"),
signal(BIT,0, "ack_in_progress"),
signal(BIT,0, "tmpbit"),
signal(SLV, DATA_BUS_WIDTH, "rddata_reg"),
signal(SLV, DATA_BUS_WIDTH, "wrdata_reg"),
signal(SLV, address_bus_width, "rwaddr_reg")
};
table_join(siglist, wb_sigs);
return siglist;
end
function cgen_build_portlist()
local portlist = {};
table_join(portlist, cgen_build_wishbone_ports());
table_join(portlist, cgen_build_clock_list());
table_join(portlist, tree_2_table("ports"));
return portlist;
end
function cgen_find_sigport(name)
for i,v in pairs(g_portlist) do if(name == v.name) then return v; end end
for i,v in pairs(g_siglist) do if(name == v.name) then return v; end end
return nil;
end
function cgen_build_signals_ports()
g_portlist = cgen_build_portlist();
g_siglist = cgen_build_siglist();
end
cur_indent = 0;
function indent_zero()
cur_indent=0;
end
function indent_left()
cur_indent = cur_indent - 1;
end
function indent_right()
cur_indent = cur_indent + 1;
end
function cgen_new_snippet()
emit_code = "";
end
function emiti()
local i;
for i = 1,cur_indent do emit_code=emit_code.." "; end
end
function emit(s)
local i;
for i = 1,cur_indent do emit_code=emit_code.." "; end
emit_code=emit_code..s.."\n";
end
function emitx(s)
emit_code=emit_code..s;
end
function cgen_get_snippet()
return emit_code;
end
function cgen_write_current_snippet()
hdl_file.write(hdl_file, emit_code);
end
function cgen_write_snippet(s)
hdl_file.write(hdl_file, s);
end
function cgen_generate_hdl_init(filename)
hdl_file = io.open(filename, "w");
end
function cgen_generate_hdl_done()
hdl_file.close(hdl_file);
end
#!/usr/bin/lua
-- wbgen2, (c) 2010 Tomasz Wlostowski/CERN BE-Co-HT
-- LICENSED UNDER GPL v2
-- File: cgen_vhdl.lua
-- The Verilog code generator
VLOG_WIRE = 1;
VLOG_REG = 2;
function cgen_verilog_header()
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("// Title : Wishbone slave core for "..periph.name);
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("// File : "..options.output_hdl_file);
emit("// Author : auto-generated by wbgen2 from "..input_wb_file);
emit("// Created : "..os.date());
emit("// Standard : Verilog 2001");
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("// THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE "..input_wb_file);
emit("// DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!");
emit("//////////////////////////////////////////////////////////////////////////////////////");
emit("");
end
function cgen_verilog_module()
local last;
indent_zero();
emit ("module "..periph.hdl_entity.." (");
indent_right();
for i=1,table.getn(g_portlist) do
local port = g_portlist[i];
if(i == table.getn(g_portlist)) then
last = true;
else
last = false;
end
if(port.comment ~= nil) then
emitx("// "..port.comment.."\n");
end
local dirstr;
if(port.dir=="in") then
dirstr="input";
elseif(port.dir=="out") then
dirstr="output";
elseif(port.dir=="inout") then
dirst="inout";
end
print("Port: ", port.name, "type ", port.vlog_type);
if(port.vlog_type == VLOG_REG) then
dirstr=dirstr.." reg";
end
local rangestr="";
if(port.range > 0) then
rangestr = "["..(port.range-1)..":0]";
end
local line = string.format("%-11s %-6s %s", dirstr, rangestr, port.name);
line=line..csel(last, "", ",");
emit(line);
end
indent_left();
emit(");");
indent_left();
emit("");
for i,v in pairs (g_siglist) do
local rwire=csel(v.vlog_type==VLOG_REG, "reg", "wire");
local rangestr="";
if(v.range > 0) then
rangestr=string.format("[%d:0] ", v.range-1);
end
emit(string.format("%-5s %-7s %s;", rwire, rangestr, v.name));
end
emit("");
indent_right();
end
function cgen_verilog_ending()
indent_left();
emit("endmodule");
end
-- Generates the vlog code from syntax tree <tree>, writing it into previously chosen file.
function cgen_generate_verilog_code(tree)
local inside_process = false;
function find_code(node, t)
for i,v in ipairs(node) do if ((v.t ~= nil) and (v.t == t)) then return v; end end
return nil;
end
function cgen_verilog_syncprocess(node)
local vrst = find_code(node.code, "reset");
if(vrst ~= nil and options.reset_type=="asynchronous") then
emit("always @(posedge "..node.clk.." or "..csel(vrst.level==0, "negedge", "posedge").." rst_n_i) begin")
else
emit("always @(posedge "..node.clk..") begin");
end
indent_right();
inside_process = true;
local vpe = find_code(node.code, "posedge");
if(vpe == nil) then die("verilog code generation error: no vposedge defined for vsyncprocess"); end
if(vrst ~= nil) then
emit("if ("..node.rst.." == 1'b"..vrst.level..") begin ");
indent_right();
recurse(vrst.code);
indent_left();
emit("end else begin");
indent_right();
end
recurse(vpe.code);
if(vrst ~= nil) then
indent_left();
emit("end");
end
indent_left();
emit("end");
emit("");
inside_process = false;
end
function node_typesize(node)
local ts = {};
local sig;
print(node);
if(type(node) == "table") then
print("table!");
if(node.t ~= nil and node.t == "index") then
sig = cgen_find_sigport(node.name);
ts.h=node.h;
ts.l=node.l;
ts.sig=sig;
ts.name=sig.name;
ts.type=sig.type;
ts.size = csel(ts.l==nil,1,ts.h-ts.l+1);
return ts;
else
print("expr2: ", node.t);
ts.type = EXPRESSION;
ts.code = node;
return ts;
end
elseif(type(node) == "string") then
print("string-type node: "..node);
sig = cgen_find_sigport(node);
ts.sig=sig;
ts.size = sig.range;
ts.type = sig.type;
ts.name = node;
return ts;
elseif(type(node) == "number") then
ts.type = INTEGER;
ts.name = node;
ts.size = 0;
return ts;
else
print("Unknown node?");
end
end
function gen_subrange(t)
if(t.h ~= nil and t.l == nil) then
return t.name.."["..t.h.."]";
elseif(t.h ~= nil and t.l ~= nil) then
return t.name.."["..t.h..":"..t.l.."]";
else
return t.name;
end
end
function calc_size(t)
if(t.h ~= nil and t.l == nil) then
return 1;
elseif(t.h ~= nil and t.l ~= nil) then
return t.h-t.l+1;
else
local sig= cgen_find_sigport(t.name);
return sig.range;
end
end
function cgen_verilog_assign(node)
local tsd = node_typesize(node.dst);
local tss = node_typesize(node.src);
-- for i,v in pairs(tsd) do
-- print(i,v);
-- end
-- vlog synchronous assignment
if(inside_process) then
if(tss.type == EXPRESSION) then
print("EXPR!");
emiti();
emitx(gen_subrange(tsd).." <= ");
tsd.sig.vlog_type = VLOG_REG;
recurse({tss.code});
emitx(";\n");
else
emit(gen_subrange(tsd).." <= "..gen_subrange(tss)..";");
tsd.sig.vlog_type = VLOG_REG;
end
else -- vlog combinatorial assignment
emit("assign "..gen_subrange(tsd).." = "..gen_subrange(tss)..";");
tsd.sig.vlog_type = VLOG_WIRE;
end
end
function cgen_verilog_if(node)
emiti(); emitx("if (");
-- print("EMIT IF:", node.cond);
for i,v in pairs(node.cond) do print(i,v); end
recurse(node.cond);
emitx(") begin\n");
if(node.code_else ~= nil) then
indent_right();
recurse(node.code);
indent_left();
emit("end else begin");
indent_right();
recurse(node.code_else);
indent_left();
emit("end");
else
indent_right();
recurse(node.code);
indent_left();
emit("end");
end
end
function cgen_verilog_not(node)
local tsa = node_typesize(node.a);
emitx("! ");
if(tsa.type == EXPRESSION) then
emitx("("); recurse({node.a}); emitx(")");
else
emitx(gen_subrange(tsa));
end
end
function cgen_verilog_op(node, op)
local tsa = node_typesize(node.a);
local tsb = node_typesize(node.b);
if(tsa.type == EXPRESSION) then
emitx("("); recurse({node.a}); emitx(")");
else
emitx(gen_subrange(tsa));
end
if(op=="eq") then emitx(" == "); end
if(op=="and") then emitx(" && "); end
if(op=="or") then emitx(" || "); end
if(op=="sub") then emitx(" - "); end
if(op=="add") then emitx(" + "); end
if(tsb.type == EXPRESSION) then
emitx("("); recurse({node.b}); emitx(")");
else
emitx(gen_subrange(tsb));
end
end
function cgen_verilog_comment(node)
emitx("// "..node.str.."\n");
end
-- switch/case statement --
function cgen_verilog_switch(node)
local tsa = node_typesize(node.a);
emiti(); emitx("case ");
if(tsa.type == EXPRESSION) then
emitx("("); recurse({node.a}); emitx(")");
else
emitx("("..gen_subrange(tsa)..")");
end
emit("");
for i,v in pairs(node.code) do
print("CA: ", v.t);
if(v.t == "case") then
emit(string.format("%d'h%x: begin", tsa.size, v.a));
indent_right();
recurse({v.code});
indent_left();
emit("end");
elseif(v.t == "casedefault") then
emit("default: begin");
indent_right();
recurse({v.code});
indent_left();
emit("end");
end
end
emit("endcase");
end
function recurse(t)
print("recurse: ", t);
for i,v in pairs(t) do
print("-> i ",i,"v ",v, "vt ",v.t);
if(v.t == nil) then
recurse(v);
elseif(v.t == "comment") then
cgen_verilog_comment(v);
elseif(v.t == "syncprocess") then
cgen_verilog_syncprocess(v);
elseif(v.t=="assign") then
cgen_verilog_assign(v);
elseif(v.t=="if") then
cgen_verilog_if(v);
elseif(v.t=="eq" or v.t=="sub" or v.t=="add" or v.t == "or" or v.t=="and") then
cgen_verilog_op(v,v.t);
elseif(v.t=="switch") then
cgen_verilog_switch(v);
elseif(v.t=="not") then
cgen_verilog_not(v);
else
print("unimpl: "..v.t);
os.exit(-1);
end
end
print("end recurse");
end
cgen_new_snippet();
cgen_verilog_header();
local c_header = cgen_get_snippet();
cgen_new_snippet();
recurse(tree);
cgen_verilog_ending();
local c_body = cgen_get_snippet();
-- generate the module definions and signals - this must done after the module body has been generated in order to determine whether to declare things
-- as regs or wires.
cgen_new_snippet();
cgen_verilog_module();
local c_mod = cgen_get_snippet();
cgen_write_snippet(c_header);
cgen_write_snippet(c_mod);
cgen_write_snippet(c_body);
--cgen_write_snippet();
end
This diff is collapsed.
[General]
def_graphic_ext=eps
img_extIsRegExp=false
img_extensions=.eps .jpg .jpeg .png .pdf .ps .fig .gif
kileprversion=2
kileversion=2.0.84
lastDocument=regs.tex
masterDocument=
name=wbgen2_doc
pkg_extIsRegExp=false
pkg_extensions=.cls .sty .bbx .cbx .lbx
src_extIsRegExp=false
src_extensions=.tex .ltx .latex .dtx .ins
[Tools]
MakeIndex=
QuickBuild=
[item:intro.tex]
archive=true
column=1
encoding=
highlight=
line=0
mode=
open=false
order=-1
[item:main.tex]
archive=true
column=0
encoding=UTF-8
highlight=LaTeX
line=76
mode=LaTeX
open=true
order=0
[item:processing.tex]
archive=true
column=0
encoding=UTF-8
highlight=LaTeX
line=6
mode=LaTeX
open=true
order=1
[item:regs.tex]
archive=true
column=101
encoding=UTF-8
highlight=LaTeX
line=12
mode=LaTeX
open=true
order=2
[item:title.tex]
archive=true
column=167092456
encoding=
highlight=
line=0
mode=
open=false
order=-1
[item:wbgen2_doc.kilepr]
archive=true
column=7209065
encoding=
highlight=
line=0
mode=
open=false
order=-1
[view-settings,view=0,item:main.tex]
CursorColumn=0
CursorLine=76
[view-settings,view=0,item:processing.tex]
CursorColumn=0
CursorLine=6
[view-settings,view=0,item:regs.tex]
CursorColumn=101
CursorLine=12
This diff is collapsed.
This diff is collapsed.
......@@ -2,12 +2,20 @@
wbgen2_version="0.3"
wbgen2_libdir="/home/slayer/wbgen2-dev"
wbgen2_libdir="."
device_family="altera_cyclone3";
options = {};
options.reset_type = "asynchronous";
options.target_interconnect = "wishbone";
dofile(wbgen2_libdir.."/wbgen_common.lua");
dofile(wbgen2_libdir.."/wbgen_vhdl.lua");
dofile(wbgen2_libdir.."/cgen_common.lua");
dofile(wbgen2_libdir.."/cgen_vhdl.lua");
dofile(wbgen2_libdir.."/cgen_verilog.lua");
dofile(wbgen2_libdir.."/wbgen_regbank.lua");
dofile(wbgen2_libdir.."/wbgen_rams.lua");
......@@ -46,7 +54,7 @@ function parse_args(arg)
local sw = arg[n];
if(sw == "-vo") then
output_vhdl_file = chk_nil(arg[n+1], "VHDL output filename expected");
options.output_hdl_file = chk_nil(arg[n+1], "HDL output filename expected");
n=n+2;
elseif(sw == "-co") then
output_c_file = chk_nil(arg[n+1], "C header output filename expected");
......@@ -97,9 +105,10 @@ assign_addresses();
--foreach_reg(gen_vhdl_signals);
--foreach_reg(gen_vhdl_constants);
tree=gen_hdl_regbank();
gen_vhdl_code(output_vhdl_file);
cgen_build_signals_ports();
cgen_generate_hdl_init(options.output_hdl_file)
cgen_generate_vhdl_code(tree);
cgen_generate_hdl_done();
if(vlog_gen_reg_constants) then
gen_vlog_constants(output_vlog_constants_file);
end
......@@ -36,6 +36,8 @@ SIGNED = 0x8;
UNSIGNED = 0x10;
ENUM = 0x20;
PASS_THROUGH = 0x40;
INTEGER = 0x80;
EXPRESSION = 0x100;
LOAD_INT = 1;
LOAD_EXT = 2;
......@@ -415,4 +417,4 @@ function remove_duplicates(t)
i=i+1;
end
end
\ No newline at end of file
end
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