Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
Wishbone slave generator
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
24
Issues
24
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Wishbone slave generator
Commits
f4b155be
Commit
f4b155be
authored
Apr 19, 2013
by
Grzegorz Daniluk
Committed by
Tomasz Wlostowski
Apr 19, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adding generation of Latex docs
parent
6649e3f0
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1109 additions
and
332 deletions
+1109
-332
cgen_doc_latex.lua
cgen_doc_latex.lua
+437
-0
squishy
squishy
+1
-0
wbgen2
wbgen2
+666
-330
wbgen_main.lua
wbgen_main.lua
+5
-2
No files found.
cgen_doc_latex.lua
0 → 100644
View file @
f4b155be
#!/usr/bin/lua
-- wbgen2, (c) 2013 Grzegorz Daniluk/CERN BE-CO-HT
-- LICENSED UNDER GPL v2
-- File: cgen_doc_latex.lua
--
-- LATEX documentation generator.
--
function
lx_htable_emit
(
tbl
)
local
temp
=
""
;
local
cell_align
=
""
;
if
(
tbl
.
data
[
1
][
1
].
style
==
nil
)
then
cell_align
=
"l "
;
elseif
(
tbl
.
data
[
1
][
1
].
style
==
"td_bit"
)
then
cell_align
=
">{\\centering\\arraybackslash}p{1.5cm} "
;
end
temp
=
"
\\
begin{tabular}{"
;
for
j
=
1
,
tbl
.
cols
do
temp
=
temp
..
cell_align
;
end
temp
=
temp
..
"}"
;
emit
(
temp
);
for
i
=
1
,
tbl
.
rows
do
local
row
=
""
;
j
=
1
;
while
j
<=
tbl
.
cols
do
row
=
row
..
tbl
.
data
[
i
][
j
].
text
;
if
(
tbl
.
data
[
i
][
j
].
style
~=
nil
)
then
if
(
tbl
.
data
[
i
][
j
].
style
==
"td_field"
)
then
j
=
j
+
tbl
.
data
[
i
][
j
].
flen
;
end
end
if
(
j
~=
tbl
.
cols
)
then
row
=
row
..
' & '
;
else
row
=
row
..
'
\\\\
'
;
end
j
=
j
+
1
;
end
emit
(
row
);
end
emit
(
"
\\
end{tabular}"
);
emit
(
""
);
end
function
cgen_doc_lx_header_and_toc
()
emit
(
'
\\
subsection{'
..
periph
.
name
..
'}'
);
emit
(
'
\\
label{subsec:wbgen:'
..
periph
.
prefix
..
'}'
);
local
t
=
periph
.
description
;
if
(
t
==
nil
)
then
t
=
""
;
end
emit
(
string.gsub
(
t
,
"
\n
"
,
"
\\\\
"
));
end
function
cgen_doc_lx_memmap
()
local
n
=
2
;
local
reg_text
=
" "
;
emit
(
'
\\
subsubsection{Memory map summary}'
);
emit
(
'
\\
rowcolors{2}{gray!25}{white}'
);
emit
(
'
\\
resizebox{\\textwidth}{!}{'
);
emit
(
'
\\
begin{tabular}{|l|l|l|l|l|}'
);
emit
(
'
\\
rowcolor{RoyalPurple}'
);
emit
(
'
\\
color{white} H/W Addr & \\color{white} Type & \\color{white} Name &'
);
emit
(
'
\\
color{white} HW prefix & \\color{white} C prefix\\\\'
);
foreach_reg
({
TYPE_REG
},
function
(
reg
)
if
(
reg
.
full_hdl_prefix
~=
nil
)
then
reg_text
=
string.format
(
"0x%x"
,
reg
.
base
)
..
'& '
;
if
(
reg
.
doc_is_fiforeg
==
nil
)
then
reg_text
=
reg_text
..
"REG & "
;
else
reg_text
=
reg_text
..
"FIFOREG & "
;
end
reg_text
=
reg_text
..
reg
.
name
..
" & "
..
reg
.
full_hdl_prefix
..
" & "
..
string.upper
(
reg
.
c_prefix
)
..
"
\\\\
"
;
reg_text
=
string.gsub
(
reg_text
,
"_"
,
"
\\
_"
);
emit
(
reg_text
);
end
end
);
foreach_reg
({
TYPE_RAM
},
function
(
reg
)
if
(
reg
.
full_hdl_prefix
~=
nil
)
then
reg_text
=
string.format
(
"0x%x - 0x%x"
,
reg
.
base
,
reg
.
base
+
math.pow
(
2
,
reg
.
wrap_bits
)
*
reg
.
size
-
1
)
..
'& '
;
reg_text
=
reg_text
..
"MEM & "
..
reg
.
name
..
" & "
..
reg
.
full_hdl_prefix
..
" & "
..
string.upper
(
reg
.
c_prefix
)
..
"
\\\\
"
;
reg_text
=
string.gsub
(
reg_text
,
"_"
,
"
\\
_"
);
emit
(
reg_text
);
end
end
);
emit
(
'
\\
end{tabular}'
);
emit
(
'}'
);
--end of resizebox
end
function
cgen_doc_lx_fieldtable
(
reg
,
bitoffs
)
local
td_width
=
70
;
local
tbl
;
local
n
=
1
;
tbl
=
htable_new
(
2
,
8
);
for
i
=
1
,
8
do
tbl
.
data
[
1
][
i
].
style
=
"td_bit"
;
tbl
.
data
[
1
][
n
].
flen
=
0
;
tbl
.
data
[
1
][
i
].
text
=
string.format
(
"%d"
,
bitoffs
+
8
-
i
);
end
local
bit
=
bitoffs
+
7
;
while
(
bit
>=
bitoffs
)
do
local
f
=
find_field_by_offset
(
reg
,
bit
);
if
(
f
==
nil
)
then
tbl
.
data
[
2
][
n
].
style
=
"td_unused"
;
tbl
.
data
[
2
][
n
].
flen
=
0
;
if
(
n
==
1
)
then
tbl
.
data
[
2
][
n
].
text
=
"
\\
multicolumn{1}{|c}{-}"
;
elseif
(
n
==
8
)
then
tbl
.
data
[
2
][
n
].
text
=
"
\\
multicolumn{1}{c|}{-}"
;
else
tbl
.
data
[
2
][
n
].
text
=
"-"
;
end
n
=
n
+
1
;
bit
=
bit
-
1
;
else
local
fend
;
if
(
f
.
offset
<
bitoffs
)
then
fend
=
bitoffs
;
else
fend
=
f
.
offset
;
end
local
ncells
=
(
bit
-
fend
)
+
1
;
dbg
(
"ncells: "
,
ncells
,
"bit: "
,
bit
,
"name: "
,
f
.
prefix
);
tbl
.
data
[
2
][
n
].
colspan
=
ncells
;
local
prefix
;
prefix
=
f
.
c_prefix
;
if
(
prefix
==
nil
)
then
prefix
=
reg
.
c_prefix
;
end
prefix
=
string.gsub
(
prefix
,
"_"
,
"
\\
_"
);
tbl
.
data
[
2
][
n
].
style
=
"td_field"
;
tbl
.
data
[
2
][
n
].
flen
=
bit
-
fend
;
tbl
.
data
[
2
][
n
].
text
=
csel
(
f
.
size
>
1
,
string.format
(
"
\\
multicolumn{%d}{|c|}{\\cellcolor{RoyalPurple!25}%s[%d:%d]}"
,
bit
-
fend
+
1
,
string.upper
(
prefix
),
bit
-
f
.
offset
,
fend
-
f
.
offset
),
string.format
(
"
\\
multicolumn{1}{|c|}{\\cellcolor{RoyalPurple!25}%s}"
,
string.upper
(
prefix
)));
bit
=
bit
-
ncells
;
n
=
n
+
1
;
end
end
--part of htable_emit()
for
i
=
1
,
tbl
.
rows
do
local
row
=
""
;
j
=
1
;
k
=
0
;
while
k
<
tbl
.
cols
do
row
=
row
..
tbl
.
data
[
i
][
j
].
text
;
if
(
tbl
.
data
[
i
][
j
].
style
~=
nil
)
then
if
(
tbl
.
data
[
i
][
j
].
style
==
"td_field"
)
then
k
=
k
+
tbl
.
data
[
i
][
j
].
flen
;
end
end
k
=
k
+
1
;
if
(
k
~=
tbl
.
cols
)
then
row
=
row
..
' & '
;
else
row
=
row
..
'
\\\\
'
;
end
j
=
j
+
1
;
end
emit
(
row
);
emit
(
"
\\
hline"
);
end
end
function
cgen_doc_access
(
acc
)
if
(
acc
==
READ_ONLY
)
then
return
"read-only"
;
elseif
(
acc
==
READ_WRITE
)
then
return
"read/write"
;
elseif
(
acc
==
WRITE_ONLY
)
then
return
"write-only"
;
else
return
"FIXME!"
;
end
end
cur_reg_no
=
1
;
function
cgen_doc_lx_reg
(
reg
)
local
temp
=
""
;
local
description
=
""
;
cur_reg_no
=
cur_reg_no
+
1
;
emit
(
"
\\
paragraph*{"
..
reg
.
name
..
"}\\vspace{12pt}"
);
emit
(
""
);
local
tbl
=
htable_new
(
4
,
2
);
tbl
.
data
[
1
][
1
].
text
=
"{\\bf HW prefix:} "
;
tbl
.
data
[
2
][
1
].
text
=
"{\\bf HW address:} "
;
tbl
.
data
[
3
][
1
].
text
=
"{\\bf SW prefix:} "
;
tbl
.
data
[
4
][
1
].
text
=
"{\\bf SW offset:} "
;
tbl
.
data
[
1
][
2
].
text
=
string.gsub
(
reg
.
full_hdl_prefix
,
"_"
,
"
\\
_"
);
tbl
.
data
[
2
][
2
].
text
=
string.format
(
"0x%x"
,
reg
.
base
);
tbl
.
data
[
3
][
2
].
text
=
string.gsub
(
string.upper
(
reg
.
c_prefix
),
"_"
,
"
\\
_"
);
tbl
.
data
[
4
][
2
].
text
=
string.format
(
"0x%x"
,
reg
.
base
*
(
DATA_BUS_WIDTH
/
8
));
emit
(
"
\\
rowcolors{1}{white}{white}"
);
lx_htable_emit
(
tbl
);
if
(
reg
.
description
~=
nil
)
then
emit
(
"
\\
vspace{12pt}"
);
description
=
string.gsub
(
reg
.
description
,
"
\n
"
,
"
\\\\
"
);
description
=
string.gsub
(
description
,
"_"
,
"
\\
_"
);
description
=
string.gsub
(
description
,
"<code>"
,
"
\\
texttt{"
);
description
=
string.gsub
(
description
,
"</code>"
,
"}"
);
emit
(
description
);
end
--generate header for tabular
temp
=
"
\\
begin{tabular}{"
;
for
j
=
1
,
8
do
temp
=
temp
..
">{\\centering\\arraybackslash}p{1.5cm} "
;
end
temp
=
temp
..
"}"
;
emit
(
""
);
emit
(
"
\\
vspace{12pt}"
);
emit
(
"
\\
noindent"
);
emit
(
'
\\
resizebox{\\textwidth}{!}{'
);
emit
(
temp
);
for
i
=
0
,
DATA_BUS_WIDTH
/
8
-
1
do
cgen_doc_lx_fieldtable
(
reg
,
(
DATA_BUS_WIDTH
/
8
-
1
-
i
)
*
8
);
end
emit
(
"
\\
end{tabular}"
);
emit
(
"}"
);
emit
(
""
);
emit
(
"
\\
begin{itemize}"
);
foreach_subfield
(
reg
,
function
(
field
)
emit
(
"
\\
item \\begin{small}"
);
emit
(
"{\\bf "
);
if
(
field
.
c_prefix
==
nil
)
then
-- anonymous field?
emit
(
string.gsub
(
string.upper
(
reg
.
c_prefix
),
"_"
,
"
\\
_"
));
else
emit
(
string.gsub
(
string.upper
(
field
.
c_prefix
),
"_"
,
"
\\
_"
));
end
emit
(
"} [\\emph{"
..
cgen_doc_access
(
field
.
access_bus
)
..
"}]: "
..
field
.
name
);
if
(
field
.
description
~=
nil
)
then
emit
(
"
\\\\
"
);
description
=
string.gsub
(
field
.
description
,
"
\n
"
,
"
\\\\
"
);
description
=
string.gsub
(
description
,
"_"
,
"
\\
_"
);
description
=
string.gsub
(
description
,
"<code>"
,
"
\\
texttt{"
);
description
=
string.gsub
(
description
,
"</code>"
,
"}"
);
emit
(
description
);
end
emit
(
"
\\
end{small}"
);
end
);
emit
(
"
\\
end{itemize}"
);
end
cur_mem_no
=
1
;
function
cgen_doc_lx_ram
(
ram
)
local
description
=
""
;
emit
(
"
\\
paragraph*{"
..
ram
.
name
..
"}\\vspace{12pt}"
);
emit
(
""
);
cur_mem_no
=
cur_mem_no
+
1
;
local
tbl
=
htable_new
(
11
,
2
);
tbl
.
data
[
1
][
1
].
text
=
"{\\bf HW prefix:} "
;
tbl
.
data
[
2
][
1
].
text
=
"{\\bf HW address:} "
;
tbl
.
data
[
3
][
1
].
text
=
"{\\bf C prefix:} "
;
tbl
.
data
[
4
][
1
].
text
=
"{\\bf C offset:} "
;
tbl
.
data
[
5
][
1
].
text
=
"{\\bf Size:} "
;
tbl
.
data
[
6
][
1
].
text
=
"{\\bf Data width:} "
;
tbl
.
data
[
7
][
1
].
text
=
"{\\bf Access (bus):} "
;
tbl
.
data
[
8
][
1
].
text
=
"{\\bf Access (device):} "
;
tbl
.
data
[
9
][
1
].
text
=
"{\\bf Mirrored:} "
;
tbl
.
data
[
10
][
1
].
text
=
"{\\bf Byte-addressable:} "
;
tbl
.
data
[
11
][
1
].
text
=
"{\\bf Peripheral port:} "
;
tbl
.
data
[
1
][
2
].
text
=
string.lower
(
string.gsub
(
periph
.
hdl_prefix
,
"_"
,
"
\\
_"
)
..
"
\\
_"
..
string.gsub
(
ram
.
hdl_prefix
,
"_"
,
"
\\
_"
));
tbl
.
data
[
2
][
2
].
text
=
string.format
(
"0x%x"
,
ram
.
base
);
tbl
.
data
[
3
][
2
].
text
=
string.upper
(
string.gsub
(
ram
.
c_prefix
,
"_"
,
"
\\
_"
));
tbl
.
data
[
4
][
2
].
text
=
string.format
(
"0x%x"
,
ram
.
base
*
(
DATA_BUS_WIDTH
/
8
));
tbl
.
data
[
5
][
2
].
text
=
ram
.
size
..
" "
..
ram
.
width
..
"-bit words"
;
tbl
.
data
[
6
][
2
].
text
=
ram
.
width
;
tbl
.
data
[
7
][
2
].
text
=
cgen_doc_access
(
ram
.
access_bus
);
tbl
.
data
[
8
][
2
].
text
=
cgen_doc_access
(
ram
.
access_dev
);
if
(
ram
.
byte_select
~=
nil
and
ram
.
byte_select
==
true
)
then
tbl
.
data
[
10
][
2
].
text
=
"yes"
;
else
tbl
.
data
[
10
][
2
].
text
=
"no"
;
end
if
(
ram
.
wrap_bits
~=
nil
and
0
~=
ram
.
wrap_bits
)
then
tbl
.
data
[
9
][
2
].
text
=
math.pow
(
2
,
ram
.
wrap_bits
)
..
" times"
;
else
tbl
.
data
[
9
][
2
].
text
=
"no"
;
end
if
(
ram
.
clock
~=
nil
)
then
tbl
.
data
[
11
][
2
].
text
=
"asynchronous ("
..
ram
.
clock
..
")"
;
else
tbl
.
data
[
11
][
2
].
text
=
"bus-synchronous"
;
end
emit
(
"
\\
begin{small}"
);
lx_htable_emit
(
tbl
);
emit
(
"
\\
end{small}"
);
if
(
ram
.
description
~=
nil
)
then
description
=
string.gsub
(
ram
.
description
,
"
\n
"
,
"
\\\\
"
);
description
=
string.gsub
(
description
,
"_"
,
"
\\
_"
);
description
=
string.gsub
(
description
,
"<code>"
,
"
\\
texttt{"
);
description
=
string.gsub
(
description
,
"</code>"
,
"}"
);
emit
(
description
);
end
end
cur_irq_no
=
1
;
function
cgen_doc_lx_irq
(
irq
)
local
description
=
""
;
emit
(
"
\\
paragraph*{"
..
irq
.
name
..
"}\\vspace{12pt}"
);
cur_irq_no
=
cur_irq_no
+
1
;
local
tbl
=
htable_new
(
3
,
2
);
tbl
.
data
[
1
][
1
].
text
=
"{\\bf HW prefix:} "
;
tbl
.
data
[
2
][
1
].
text
=
"{\\bf C prefix:} "
;
tbl
.
data
[
3
][
1
].
text
=
"{\\bf Trigger:} "
;
tbl
.
data
[
1
][
2
].
text
=
string.gsub
(
string.lower
(
periph
.
hdl_prefix
..
"_"
..
irq
.
hdl_prefix
),
"_"
,
"
\\
_"
);
tbl
.
data
[
2
][
2
].
text
=
string.upper
(
string.gsub
(
irq
.
c_prefix
,
"_"
,
"
\\
_"
));
local
trigtab
=
{
[
EDGE_RISING
]
=
"rising edge"
;
[
EDGE_FALLING
]
=
"falling edge"
;
[
LEVEL_0
]
=
"low level"
;
[
LEVEL_1
]
=
"high level"
;
};
tbl
.
data
[
3
][
2
].
text
=
trigtab
[
irq
.
trigger
];
emit
(
"
\\
begin{small}"
);
lx_htable_emit
(
tbl
);
emit
(
"
\\
end{small}"
);
if
(
irq
.
description
~=
nil
)
then
emit
(
"
\\
vspace{12pt}"
);
description
=
string.gsub
(
irq
.
description
,
"
\n
"
,
"
\\\\
"
);
description
=
string.gsub
(
description
,
"_"
,
"
\\
_"
);
description
=
string.gsub
(
description
,
"<code>"
,
"
\\
texttt{"
);
description
=
string.gsub
(
description
,
"</code>"
,
"}"
);
emit
(
description
);
end
end
function
cgen_generate_latex_documentation
()
cgen_new_snippet
();
emit
(
"
\\
subsubsection{Register description}"
);
foreach_reg
({
TYPE_REG
},
function
(
reg
)
if
(
reg
.
no_docu
==
nil
or
reg
.
no_docu
==
false
)
then
cgen_doc_lx_reg
(
reg
);
end
end
);
local
h_regs
=
cgen_get_snippet
();
local
h_rams
=
""
;
if
(
periph
.
ramcount
>
0
)
then
emit
(
"
\\
subsubsection{Memory blocks}"
);
cgen_new_snippet
();
foreach_reg
({
TYPE_RAM
},
function
(
reg
)
if
(
reg
.
no_docu
==
nil
or
reg
.
no_docu
==
false
)
then
cgen_doc_lx_ram
(
reg
);
end
end
);
h_rams
=
cgen_get_snippet
();
end
local
h_irqs
=
""
;
if
(
periph
.
irqcount
>
0
)
then
cgen_new_snippet
();
emit
(
"
\\
subsubsection{Interrupts}"
);
foreach_reg
({
TYPE_IRQ
},
function
(
reg
)
if
(
reg
.
no_docu
==
nil
or
reg
.
no_docu
==
false
)
then
cgen_doc_lx_irq
(
reg
);
end
end
);
h_irqs
=
cgen_get_snippet
();
end
cgen_new_snippet
();
cgen_doc_lx_memmap
();
local
h_memmap
=
cgen_get_snippet
();
cgen_new_snippet
();
cgen_doc_lx_header_and_toc
();
emit
(
h_memmap
);
emit
(
h_regs
);
emit
(
h_rams
);
emit
(
h_irqs
);
cgen_write_current_snippet
();
end
squishy
View file @
f4b155be
...
...
@@ -14,6 +14,7 @@ Main "cgen_verilog.lua"
Main "cgen_c_headers.lua"
Main "cgen_doc.lua"
Main "cgen_doc_texinfo.lua"
Main "cgen_doc_latex.lua"
Main "wbgen_regbank.lua"
Main "wbgen_rams.lua"
Main "wbgen_eic.lua"
...
...
wbgen2
View file @
f4b155be
#!/usr/bin/env lua
package.preload
[
'alt_getopt'
]
=
(
function
(
...
)
local
i
,
h
,
u
,
o
,
a
=
type
,
pairs
,
ipairs
,
io
,
os
local
o
,
d
,
u
,
a
,
i
=
type
,
pairs
,
ipairs
,
io
,
os
module
(
"alt_getopt"
)
local
function
r
(
e
)
local
t
=
1
local
t
=#
e
local
t
=
{}
for
e
,
a
in
e
:
gmatch
(
"(%w)(:?)"
)
do
t
[
e
]
=#
a
local
function
c
(
t
)
local
e
=
1
local
e
=#
t
local
e
=
{}
for
a
,
t
in
t
:
gmatch
(
"(%w)(:?)"
)
do
e
[
a
]
=#
t
end
return
t
return
e
end
local
function
d
(
e
,
t
)
o
.
stderr
:
write
(
e
)
a
.
exit
(
t
)
local
function
r
(
t
,
e
)
a
.
stderr
:
write
(
t
)
i
.
exit
(
e
)
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
o
(
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
,
o
,
a
)
function
get_ordered_opts
(
n
,
a
,
s
)
local
t
=
1
local
e
=
1
local
i
=
{}
local
s
=
{}
local
o
=
r
(
o
)
for
e
,
t
in
h
(
a
)
do
local
h
=
{}
local
o
=
c
(
a
)
for
e
,
t
in
d
(
s
)
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
h
=
a
:
find
(
"="
,
1
,
true
)
if
h
then
local
t
=
a
:
sub
(
3
,
h
-
1
)
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
)
r
(
"Bad usage of option `"
..
a
..
"'\n"
,
1
)
end
s
[
e
]
=
a
:
sub
(
h
+
1
)
h
[
e
]
=
a
:
sub
(
s
+
1
)
i
[
e
]
=
t
else
local
h
=
a
:
sub
(
3
)
h
=
l
(
o
,
h
)
if
o
[
h
]
==
0
then
i
[
e
]
=
h
local
s
=
a
:
sub
(
3
)
s
=
l
(
o
,
s
)
if
o
[
s
]
==
0
then
i
[
e
]
=
s
else
if
t
==#
n
then
d
(
"Missed value for option `"
..
a
..
"'\n"
,
1
)
r
(
"Missed value for option `"
..
a
..
"'\n"
,
1
)
end
s
[
e
]
=
n
[
t
+
1
]
i
[
e
]
=
h
h
[
e
]
=
n
[
t
+
1
]
i
[
e
]
=
s
t
=
t
+
1
end
end
e
=
e
+
1
elseif
a
:
sub
(
1
,
1
)
==
"-"
then
local
h
for
r
=
2
,
a
:
len
()
do
local
h
=
l
(
o
,
a
:
sub
(
r
,
r
))
if
o
[
h
]
==
0
then
i
[
e
]
=
h
local
s
for
d
=
2
,
a
:
len
()
do
local
s
=
l
(
o
,
a
:
sub
(
d
,
d
))
if
o
[
s
]
==
0
then
i
[
e
]
=
s
e
=
e
+
1
elseif
a
:
len
()
==
r
then
elseif
a
:
len
()
==
d
then
if
t
==#
n
then
d
(
"Missed value for option `-"
..
h
..
"'\n"
,
1
)
r
(
"Missed value for option `-"
..
s
..
"'\n"
,
1
)
end
s
[
e
]
=
n
[
t
+
1
]
i
[
e
]
=
h
h
[
e
]
=
n
[
t
+
1
]
i
[
e
]
=
s
t
=
t
+
1
e
=
e
+
1
break
else
s
[
e
]
=
a
:
sub
(
r
+
1
)
i
[
e
]
=
h
h
[
e
]
=
a
:
sub
(
d
+
1
)
i
[
e
]
=
s
e
=
e
+
1
break
end
...
...
@@ -100,16 +100,16 @@ break
end
t
=
t
+
1
end
return
i
,
t
,
s
return
i
,
t
,
h
end
function
get_opts
(
t
,
a
,
o
)
function
get_opts
(
a
,
t
,
o
)
local
e
=
{}
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
]
local
t
,
i
,
o
=
get_ordered_opts
(
a
,
t
,
o
)
for
t
,
a
in
u
(
t
)
do
if
o
[
t
]
then
e
[
a
]
=
o
[
t
]
else
e
[
t
]
=
1
e
[
a
]
=
1
end
end
return
e
,
i
...
...
@@ -176,22 +176,22 @@ die(t.." expected.");
end
return
e
;
end
function
range2bits
(
e
)
local
t
=
e
[
1
];
local
a
=
e
[
2
];
local
e
;
if
(
math.abs
(
t
)
>
math.abs
(
a
))
then
e
=
math.abs
(
t
);
function
range2bits
(
t
)
local
e
=
t
[
1
];
local
a
=
t
[
2
];
local
t
;
if
(
math.abs
(
e
)
>
math.abs
(
a
))
then
t
=
math.abs
(
e
);
else
e
=
math.abs
(
a
);
t
=
math.abs
(
a
);
end
local
e
=
math.ceil
(
math.log
(
e
)
/
math.log
(
2
));
if
(
t
<
0
)
then
e
=
e
+
1
;
local
t
=
math.ceil
(
math.log
(
t
)
/
math.log
(
2
));
if
(
e
<
0
)
then
t
=
t
+
1
;
end
return
e
;
return
t
;
end
function
calc_size
(
e
,
t
)
function
calc_size
(
e
,
a
)
if
(
e
.
type
==
MONOSTABLE
or
e
.
type
==
BIT
)
then
e
.
size
=
1
;
elseif
(
e
.
type
==
SLV
or
e
.
type
==
PASS_THROUGH
)
then
...
...
@@ -212,16 +212,16 @@ end
elseif
(
e
.
type
==
ENUM
)
then
die
(
"ENUM-type fields are not yet supported. Sorry :("
);
end
t
.
total_size
=
t
.
total_size
+
e
.
size
;
a
.
total_size
=
a
.
total_size
+
e
.
size
;
end
function
foreach_reg
(
a
,
t
,
e
)
function
foreach_reg
(
t
,
a
,
e
)
if
(
e
==
nil
)
then
e
=
periph
;
end
for
o
,
e
in
ipairs
(
e
)
do
if
(
type
(
e
)
==
'table'
)
then
if
(
e
.
__type
~=
nil
and
(
match
(
e
.
__type
,
a
)))
then
t
(
e
);
if
(
e
.
__type
~=
nil
and
(
match
(
e
.
__type
,
t
)))
then
a
(
e
);
end
end
end
...
...
@@ -248,27 +248,27 @@ if(t.align==nil)then e=1;else e=t.align;end
local
e
=
e
*
math.floor
((
a
+
e
-
1
)
/
e
);
return
e
;
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
)
...
...
@@ -286,15 +286,15 @@ if(t==e)then return true;end
end
return
false
;
end
function
inset
(
t
,
e
)
for
a
,
e
in
ipairs
(
e
)
do
if
(
t
==
e
)
then
return
true
;
end
end
function
inset
(
e
,
t
)
for
a
,
t
in
ipairs
(
t
)
do
if
(
e
==
t
)
then
return
true
;
end
end
return
false
;
end
function
csel
(
t
,
a
,
e
)
if
(
t
)
then
return
a
;
else
function
csel
(
a
,
e
,
t
)
if
(
a
)
then
return
e
;
else
return
t
;
end
end
function
check_field_types
(
e
)
...
...
@@ -318,13 +318,13 @@ return e;
end
return
e
;
end
function
default_access
(
e
,
t
,
a
,
o
)
if
(
e
.
type
==
t
)
then
function
default_access
(
e
,
o
,
a
,
t
)
if
(
e
.
type
==
o
)
then
if
(
e
.
access_bus
==
nil
)
then
e
.
access_bus
=
a
;
end
if
(
e
.
access_dev
==
nil
)
then
e
.
access_dev
=
o
;
e
.
access_dev
=
t
;
end
end
end
...
...
@@ -369,9 +369,9 @@ end
function
log2up
(
e
)
return
math.ceil
(
math.log
(
e
)
/
math.log
(
2
));
end
function
is_power_of_2
(
t
)
for
e
=
1
,
24
do
if
(
t
==
math.pow
(
2
,
e
))
then
return
true
;
end
function
is_power_of_2
(
e
)
for
t
=
1
,
24
do
if
(
e
==
math.pow
(
2
,
t
))
then
return
true
;
end
end
return
false
;
end
...
...
@@ -426,36 +426,36 @@ table.insert(t,e);
end
end
function
tree_2_table
(
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
]);
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
]);
else
table.insert
(
a
,
t
[
e
]);
table.insert
(
t
,
a
[
e
]);
end
end
foreach_subfield
(
t
,
function
(
t
,
o
)
if
(
t
[
e
]
~=
nil
)
then
if
(
type
(
t
[
e
])
==
'table'
)
then
table_join
(
a
,
t
[
e
]);
foreach_subfield
(
a
,
function
(
a
,
o
)
if
(
a
[
e
]
~=
nil
)
then
if
(
type
(
a
[
e
])
==
'table'
)
then
table_join
(
t
,
a
[
e
]);
else
table.insert
(
a
,
t
[
e
]);
table.insert
(
t
,
a
[
e
]);
end
end
end
);
end
);
return
a
;
return
t
;
end
function
remove_duplicates
(
o
)
function
count_entries
(
t
,
a
)
function
remove_duplicates
(
a
)
function
count_entries
(
a
,
t
)
local
o
,
o
,
e
;
e
=
0
;
for
o
,
t
in
ipairs
(
t
)
do
if
(
t
==
a
)
then
e
=
e
+
1
;
end
end
for
o
,
a
in
ipairs
(
a
)
do
if
(
a
==
t
)
then
e
=
e
+
1
;
end
end
return
e
;
end
local
e
=
{};
for
a
,
t
in
ipairs
(
o
)
do
for
a
,
t
in
ipairs
(
a
)
do
local
a
=
count_entries
(
e
,
t
);
if
(
a
==
0
)
then
table.insert
(
e
,
t
);
...
...
@@ -464,67 +464,67 @@ end
return
e
;
end
function
wbgen_count_subblocks
()
local
t
=
0
;
local
o
=
0
;
local
a
=
0
;
local
e
=
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
(
e
)
o
=
o
+
1
;
end
);
foreach_reg
({
TYPE_IRQ
},
function
(
t
)
e
=
e
+
1
;
end
);
periph
.
ramcount
=
t
;
periph
.
fifocount
=
o
;
periph
.
regcount
=
a
;
periph
.
irqcount
=
e
;
if
(
t
+
o
+
a
+
e
==
0
)
then
local
t
=
0
;
foreach_reg
({
TYPE_RAM
},
function
(
e
)
o
=
o
+
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
)
t
=
t
+
1
;
end
);
periph
.
ramcount
=
o
;
periph
.
fifocount
=
a
;
periph
.
regcount
=
e
;
periph
.
irqcount
=
t
;
if
(
o
+
a
+
e
+
t
==
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
o
=
{}
local
function
a
(
e
)
if
type
(
e
)
~=
"table"
then
return
e
elseif
t
[
e
]
then
return
t
[
e
]
elseif
o
[
e
]
then
return
o
[
e
]
end
local
o
=
{}
t
[
e
]
=
o
for
t
,
e
in
pairs
(
e
)
do
o
[
a
(
t
)]
=
a
(
e
)
local
t
=
{}
o
[
e
]
=
t
for
e
,
o
in
pairs
(
e
)
do
t
[
a
(
e
)]
=
a
(
o
)
end
return
setmetatable
(
o
,
getmetatable
(
e
))
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
(
t
,
a
,
o
)
function
vi
(
o
,
t
,
a
)
local
e
=
{};
e
.
t
=
"index"
;
e
.
name
=
t
;
e
.
h
=
a
;
e
.
l
=
o
;
e
.
name
=
o
;
e
.
h
=
t
;
e
.
l
=
a
;
return
e
;
end
function
vinstance
(
a
,
t
,
o
)
function
vinstance
(
t
,
a
,
o
)
local
e
=
{};
e
.
t
=
"instance"
;
e
.
name
=
a
;
e
.
component
=
t
;
e
.
name
=
t
;
e
.
component
=
a
;
e
.
maps
=
o
;
return
e
;
end
function
vpm
(
t
,
a
)
function
vpm
(
a
,
t
)
local
e
=
{};
e
.
t
=
"portmap"
;
e
.
to
=
t
;
e
.
from
=
a
;
e
.
to
=
a
;
e
.
from
=
t
;
return
e
;
end
function
vgm
(
t
,
a
)
...
...
@@ -534,26 +534,26 @@ e.to=t;
e
.
from
=
a
;
return
e
;
end
function
vcombprocess
(
a
,
t
)
function
vcombprocess
(
t
,
a
)
local
e
=
{};
e
.
t
=
"combprocess"
;
e
.
slist
=
a
;
e
.
code
=
t
;
e
.
slist
=
t
;
e
.
code
=
a
;
return
e
;
end
function
vsyncprocess
(
o
,
a
,
t
)
function
vsyncprocess
(
a
,
t
,
o
)
local
e
=
{};
e
.
t
=
"syncprocess"
;
e
.
clk
=
o
;
e
.
rst
=
a
;
e
.
code
=
t
;
e
.
clk
=
a
;
e
.
rst
=
t
;
e
.
code
=
o
;
return
e
;
end
function
vreset
(
t
,
a
)
function
vreset
(
a
,
t
)
local
e
=
{};
e
.
t
=
"reset"
;
e
.
level
=
t
;
e
.
code
=
a
;
e
.
level
=
a
;
e
.
code
=
t
;
return
e
;
end
function
vposedge
(
t
)
...
...
@@ -562,33 +562,33 @@ e.t="posedge";
e
.
code
=
t
;
return
e
;
end
function
vif
(
o
,
a
,
t
)
function
vif
(
t
,
a
,
o
)
local
e
=
{};
e
.
t
=
"if"
;
e
.
cond
=
{
o
};
e
.
cond
=
{
t
};
e
.
code
=
a
;
e
.
code_else
=
t
;
e
.
code_else
=
o
;
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
(
t
,
a
)
function
vand
(
a
,
t
)
local
e
=
{};
e
.
t
=
"and"
;
e
.
a
=
t
;
e
.
b
=
a
;
e
.
a
=
a
;
e
.
b
=
t
;
return
e
;
end
function
vor
(
a
,
t
)
function
vor
(
t
,
a
)
local
e
=
{};
e
.
t
=
"or"
;
e
.
a
=
a
;
e
.
b
=
t
;
e
.
a
=
t
;
e
.
b
=
a
;
return
e
;
end
function
vnot
(
t
)
...
...
@@ -604,11 +604,11 @@ e.a=t;
e
.
code
=
a
;
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
)
...
...
@@ -646,23 +646,23 @@ local e={}
e
.
t
=
"undefined"
;
return
e
;
end
function
signal
(
a
,
o
,
i
,
t
)
function
signal
(
t
,
o
,
a
,
i
)
local
e
=
{}
e
.
comment
=
t
;
e
.
type
=
a
;
e
.
comment
=
i
;
e
.
type
=
t
;
e
.
range
=
o
;
e
.
name
=
i
;
e
.
name
=
a
;
return
e
;
end
VPORT_WB
=
1
;
VPORT_REG
=
2
;
function
port
(
s
,
o
,
i
,
a
,
n
,
t
)
function
port
(
a
,
n
,
s
,
i
,
o
,
t
)
local
e
=
{}
e
.
comment
=
n
;
e
.
type
=
s
;
e
.
range
=
o
;
e
.
name
=
a
;
e
.
dir
=
i
;
e
.
comment
=
o
;
e
.
type
=
a
;
e
.
range
=
n
;
e
.
name
=
i
;
e
.
dir
=
s
;
if
(
t
~=
nil
)
then
if
(
t
==
VPORT_WB
)
then
e
.
is_wb
=
true
;
...
...
@@ -795,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
,
o
)
if
(
o
==
1
)
then
function
gen_vhdl_bin_literal
(
i
,
a
)
if
(
a
==
1
)
then
return
string.format
(
"'%d'"
,
csel
(
i
==
0
,
0
,
1
));
end
local
t
=
'
\"
'
;
local
s
,
a
,
n
,
e
;
a
=
i
;
e
=
math.pow
(
2
,
o
-
1
);
local
s
,
o
,
n
,
e
;
o
=
i
;
e
=
math.pow
(
2
,
a
-
1
);
if
(
i
==
nil
)
then
for
e
=
1
,
o
do
for
e
=
1
,
a
do
t
=
t
..
"X"
;
end
else
for
o
=
1
,
o
do
n
=
math.floor
(
a
/
e
);
for
a
=
1
,
a
do
n
=
math.floor
(
o
/
e
);
t
=
t
..
csel
(
n
>
0
,
"1"
,
"0"
);
a
=
a
%
e
;
o
=
o
%
e
;
e
=
e
/
2
;
end
end
...
...
@@ -912,15 +912,15 @@ indent_left();
emit
(
""
);
emit
(
"constant c_"
..
periph
.
hdl_prefix
..
"_"
..
o
..
"_registers_init_value: t_"
..
periph
.
hdl_prefix
..
"_"
..
o
..
"_registers := ("
);
indent_right
();
for
t
=
1
,
table
.
getn
(
a
)
do
local
e
=
a
[
t
];
line
=
strip_periph_prefix
(
e
.
name
)
..
" => "
;
if
(
e
.
range
>
1
)
then
for
e
=
1
,
table
.
getn
(
a
)
do
local
t
=
a
[
e
];
line
=
strip_periph_prefix
(
t
.
name
)
..
" => "
;
if
(
t
.
range
>
1
)
then
line
=
line
..
"(others => '0')"
else
line
=
line
..
"'0'"
end
if
(
t
~=
table
.
getn
(
a
))
then
if
(
e
~=
table
.
getn
(
a
))
then
line
=
line
..
","
;
end
emit
(
line
);
...
...
@@ -1049,22 +1049,22 @@ emit("end process;");
emit
(
""
);
emit
(
""
);
end
function
cgen_vhdl_combprocess
(
t
)
local
e
=
true
;
function
cgen_vhdl_combprocess
(
e
)
local
t
=
true
;
emiti
();
emitx
(
"process ("
);
for
a
,
t
in
pairs
(
t
.
slist
)
do
if
(
e
)
then
e
=
false
;
for
a
,
e
in
pairs
(
e
.
slist
)
do
if
(
t
)
then
t
=
false
;
else
emitx
(
", "
);
end
emitx
(
t
);
emitx
(
e
);
end
emit
(
")"
);
emit
(
"begin"
);
indent_right
();
recurse
(
t
.
code
);
recurse
(
e
.
code
);
indent_left
();
emit
(
"end process;"
);
emit
(
""
);
...
...
@@ -1168,16 +1168,16 @@ else
die
(
"unsupported assignment: "
..
t
.
name
..
" "
..
e
.
name
);
end
else
die
(
"unsupported assignment: "
..
t
.
name
..
" "
..
e
.
name
);
end
end
function
cgen_vhdl_assign
(
e
)
local
t
=
node_typesize
(
e
.
dst
);
local
e
=
node_typesize
(
e
.
src
);
if
(
e
.
type
==
EXPRESSION
)
then
function
cgen_vhdl_assign
(
t
)
local
e
=
node_typesize
(
t
.
dst
);
local
t
=
node_typesize
(
t
.
src
);
if
(
t
.
type
==
EXPRESSION
)
then
emiti
();
emitx
(
gen_subrange
(
t
)
..
" <= "
);
recurse
({
e
.
code
});
emitx
(
gen_subrange
(
e
)
..
" <= "
);
recurse
({
t
.
code
});
emitx
(
";\n"
);
else
emit
(
gen_subrange
(
t
)
..
" <= "
..
gen_vhdl_typecvt
(
t
,
e
)
..
";"
);
emit
(
gen_subrange
(
e
)
..
" <= "
..
gen_vhdl_typecvt
(
e
,
t
)
..
";"
);
end
end
function
cgen_vhdl_if
(
e
)
...
...
@@ -1253,25 +1253,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
...
...
@@ -1279,15 +1279,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
...
...
@@ -1776,7 +1776,7 @@ dbg("DOCREG: ",e.name,e.num_fields);
if
(
e
.
num_fields
~=
nil
and
e
.
num_fields
>
0
)
then
emit
(
""
);
emit
(
"/* definitions for register: "
..
e
.
name
..
" */"
);
foreach_subfield
(
e
,
function
(
t
,
e
)
cgen_c_field_define
(
t
,
e
)
end
);
foreach_subfield
(
e
,
function
(
e
,
t
)
cgen_c_field_define
(
e
,
t
)
end
);
end
end
);
foreach_reg
({
TYPE_RAM
},
function
(
e
)
...
...
@@ -1912,21 +1912,21 @@ end
end
return
e
;
end
function
htable_tdstyle
(
e
,
a
,
t
)
tbl
.
data
[
e
][
a
].
style
=
t
;
function
htable_tdstyle
(
a
,
t
,
e
)
tbl
.
data
[
a
][
t
].
style
=
e
;
end
function
htable_trstyle
(
e
,
a
,
t
)
tbl
.
data
[
e
].
style
=
t
;
end
function
htable_frame
(
a
,
o
,
t
,
e
)
if
(
e
==
nil
)
then
a
.
data
[
o
][
t
].
extra
=
'style="border: solid 1px black;"'
;
function
htable_frame
(
e
,
t
,
o
,
a
)
if
(
a
==
nil
)
then
e
.
data
[
t
][
o
].
extra
=
'style="border: solid 1px black;"'
;
else
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;'
;
e
.
data
[
t
][
o
].
extra
=
'style="border-left: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;'
;
e
.
data
[
t
][
a
].
extra
=
'style="border-right: solid 1px black; border-top: solid 1px black; border-bottom: solid 1px black;'
;
if
(
a
>
o
+
1
)
then
for
a
=
o
+
1
,
a
-
1
do
e
.
data
[
t
][
a
].
extra
=
'border-top: solid 1px black; border-bottom: solid 1px black;'
;
end
end
end
...
...
@@ -1964,11 +1964,11 @@ 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
,
a
)
if
(
a
>
e
.
rows
)
then
...
...
@@ -1988,8 +1988,8 @@ 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
)
...
...
@@ -2051,9 +2051,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
;
...
...
@@ -2062,33 +2062,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
(
o
)
function
cgen_doc_symbol
(
i
)
local
t
=
htable_new
(
3
,
5
);
local
a
=
1
;
local
e
=
1
;
local
i
=
true
;
for
o
,
e
in
pairs
(
o
)
do
local
o
=
true
;
for
o
,
e
in
pairs
(
i
)
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
o
,
a
in
ipairs
(
o
)
do
for
i
,
a
in
ipairs
(
i
)
do
if
(
type
(
a
)
==
"string"
)
then
if
(
i
==
false
)
then
if
(
o
==
false
)
then
htable_add_row
(
t
,
e
);
row
=
t
.
data
[
e
];
row
[
3
].
text
=
" "
;
e
=
e
+
1
;
else
i
=
false
;
o
=
false
;
end
htable_add_row
(
t
,
e
);
local
t
=
t
.
data
[
e
];
...
...
@@ -2180,27 +2180,27 @@ end
end
);
htable_emit
(
o
);
end
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
;
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
;
end
function
cgen_doc_fieldtable
(
h
,
i
)
local
e
=
70
;
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
);
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
);
end
local
a
=
i
+
7
;
while
(
a
>=
i
)
do
local
o
=
find_field_by_offset
(
h
,
a
);
if
(
o
==
nil
)
then
t
.
data
[
2
][
e
].
style
=
"td_unused"
;
t
.
data
[
2
][
e
].
text
=
"-"
;
e
=
e
+
1
;
e
.
data
[
2
][
t
].
style
=
"td_unused"
;
e
.
data
[
2
][
t
].
text
=
"-"
;
t
=
t
+
1
;
a
=
a
-
1
;
else
local
n
;
...
...
@@ -2211,18 +2211,18 @@ n=o.offset;
end
local
s
=
(
a
-
n
)
+
1
;
dbg
(
"ncells: "
,
s
,
"bit: "
,
a
,
"name: "
,
o
.
prefix
);
t
.
data
[
2
][
e
].
colspan
=
s
;
e
.
data
[
2
][
t
].
colspan
=
s
;
local
i
;
i
=
o
.
c_prefix
;
if
(
i
==
nil
)
then
i
=
h
.
c_prefix
;
end
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
);
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
);
a
=
a
-
s
;
e
=
e
+
1
;
t
=
t
+
1
;
end
end
htable_emit
(
t
);
htable_emit
(
e
);
end
function
cgen_doc_access
(
e
)
if
(
e
==
READ_ONLY
)
then
...
...
@@ -2322,47 +2322,47 @@ emit("<p>"..string.gsub(t.description,"\n","<br>").."</p>");
end
end
cur_irq_no
=
1
;
function
cgen_doc_irq
(
e
)
emit
(
hanchor
(
string.upper
(
e
.
c_prefix
),
""
));
emit
(
hsection
(
5
,
cur_irq_no
,
e
.
name
));
function
cgen_doc_irq
(
t
)
emit
(
hanchor
(
string.upper
(
t
.
c_prefix
),
""
));
emit
(
hsection
(
5
,
cur_irq_no
,
t
.
name
));
cur_irq_no
=
cur_irq_no
+
1
;
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
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
a
=
{
[
EDGE_RISING
]
=
"rising edge"
;
[
EDGE_FALLING
]
=
"falling edge"
;
[
LEVEL_0
]
=
"low level"
;
[
LEVEL_1
]
=
"high level"
;
};
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>"
);
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>"
);
end
end
function
cgen_generate_documentation
()
cgen_new_snippet
();
cgen_doc_hdl_symbol
();
local
o
=
cgen_get_snippet
();
cgen_new_snippet
();
cgen_doc_hdl_symbol
();
local
i
=
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
i
=
cgen_get_snippet
();
local
a
=
""
;
local
o
=
cgen_get_snippet
();
local
t
=
""
;
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
);
a
=
cgen_get_snippet
();
t
=
cgen_get_snippet
();
end
local
t
=
""
;
local
a
=
""
;
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
);
t
=
cgen_get_snippet
();
a
=
cgen_get_snippet
();
end
cgen_new_snippet
();
cgen_doc_memmap
();
...
...
@@ -2370,10 +2370,10 @@ local e=cgen_get_snippet();
cgen_new_snippet
();
cgen_doc_header_and_toc
();
emit
(
e
);
emit
(
o
);
emit
(
i
);
emit
(
a
);
emit
(
o
);
emit
(
t
);
emit
(
a
);
emit
(
'</BODY>'
);
emit
(
'</HTML>'
);
cgen_write_current_snippet
();
...
...
@@ -2468,6 +2468,339 @@ 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
lx_htable_emit
(
e
)
local
t
=
""
;
local
a
=
""
;
if
(
e
.
data
[
1
][
1
].
style
==
nil
)
then
a
=
"l "
;
elseif
(
e
.
data
[
1
][
1
].
style
==
"td_bit"
)
then
a
=
">{\\centering\\arraybackslash}p{1.5cm} "
;
end
t
=
"
\\
begin{tabular}{"
;
for
e
=
1
,
e
.
cols
do
t
=
t
..
a
;
end
t
=
t
..
"}"
;
emit
(
t
);
for
a
=
1
,
e
.
rows
do
local
t
=
""
;
j
=
1
;
while
j
<=
e
.
cols
do
t
=
t
..
e
.
data
[
a
][
j
].
text
;
if
(
e
.
data
[
a
][
j
].
style
~=
nil
)
then
if
(
e
.
data
[
a
][
j
].
style
==
"td_field"
)
then
j
=
j
+
e
.
data
[
a
][
j
].
flen
;
end
end
if
(
j
~=
e
.
cols
)
then
t
=
t
..
' & '
;
else
t
=
t
..
'
\\\\
'
;
end
j
=
j
+
1
;
end
emit
(
t
);
end
emit
(
"
\\
end{tabular}"
);
emit
(
""
);
end
function
cgen_doc_lx_header_and_toc
()
emit
(
'
\\
subsection{'
..
periph
.
name
..
'}'
);
emit
(
'
\\
label{subsec:wbgen:'
..
periph
.
prefix
..
'}'
);
local
e
=
periph
.
description
;
if
(
e
==
nil
)
then
e
=
""
;
end
emit
(
string.gsub
(
e
,
"
\n
"
,
"
\\\\
"
));
end
function
cgen_doc_lx_memmap
()
local
e
=
2
;
local
e
=
" "
;
emit
(
'
\\
subsubsection{Memory map summary}'
);
emit
(
'
\\
rowcolors{2}{gray!25}{white}'
);
emit
(
'
\\
resizebox{\\textwidth}{!}{'
);
emit
(
'
\\
begin{tabular}{|l|l|l|l|l|}'
);
emit
(
'
\\
rowcolor{RoyalPurple}'
);
emit
(
'
\\
color{white} H/W Addr & \\color{white} Type & \\color{white} Name &'
);
emit
(
'
\\
color{white} HW prefix & \\color{white} C prefix\\\\'
);
foreach_reg
({
TYPE_REG
},
function
(
t
)
if
(
t
.
full_hdl_prefix
~=
nil
)
then
e
=
string.format
(
"0x%x"
,
t
.
base
)
..
'& '
;
if
(
t
.
doc_is_fiforeg
==
nil
)
then
e
=
e
..
"REG & "
;
else
e
=
e
..
"FIFOREG & "
;
end
e
=
e
..
t
.
name
..
" & "
..
t
.
full_hdl_prefix
..
" & "
..
string.upper
(
t
.
c_prefix
)
..
"
\\\\
"
;
e
=
string.gsub
(
e
,
"_"
,
"
\\
_"
);
emit
(
e
);
end
end
);
foreach_reg
({
TYPE_RAM
},
function
(
t
)
if
(
t
.
full_hdl_prefix
~=
nil
)
then
e
=
string.format
(
"0x%x - 0x%x"
,
t
.
base
,
t
.
base
+
math.pow
(
2
,
t
.
wrap_bits
)
*
t
.
size
-
1
)
..
'& '
;
e
=
e
..
"MEM & "
..
t
.
name
..
" & "
..
t
.
full_hdl_prefix
..
" & "
..
string.upper
(
t
.
c_prefix
)
..
"
\\\\
"
;
e
=
string.gsub
(
e
,
"_"
,
"
\\
_"
);
emit
(
e
);
end
end
);
emit
(
'
\\
end{tabular}'
);
emit
(
'}'
);
end
function
cgen_doc_lx_fieldtable
(
h
,
i
)
local
e
=
70
;
local
e
;
local
t
=
1
;
e
=
htable_new
(
2
,
8
);
for
a
=
1
,
8
do
e
.
data
[
1
][
a
].
style
=
"td_bit"
;
e
.
data
[
1
][
t
].
flen
=
0
;
e
.
data
[
1
][
a
].
text
=
string.format
(
"%d"
,
i
+
8
-
a
);
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
].
flen
=
0
;
if
(
t
==
1
)
then
e
.
data
[
2
][
t
].
text
=
"
\\
multicolumn{1}{|c}{-}"
;
elseif
(
t
==
8
)
then
e
.
data
[
2
][
t
].
text
=
"
\\
multicolumn{1}{c|}{-}"
;
else
e
.
data
[
2
][
t
].
text
=
"-"
;
end
t
=
t
+
1
;
a
=
a
-
1
;
else
local
n
;
if
(
o
.
offset
<
i
)
then
n
=
i
;
else
n
=
o
.
offset
;
end
local
s
=
(
a
-
n
)
+
1
;
dbg
(
"ncells: "
,
s
,
"bit: "
,
a
,
"name: "
,
o
.
prefix
);
e
.
data
[
2
][
t
].
colspan
=
s
;
local
i
;
i
=
o
.
c_prefix
;
if
(
i
==
nil
)
then
i
=
h
.
c_prefix
;
end
i
=
string.gsub
(
i
,
"_"
,
"
\\
_"
);
e
.
data
[
2
][
t
].
style
=
"td_field"
;
e
.
data
[
2
][
t
].
flen
=
a
-
n
;
e
.
data
[
2
][
t
].
text
=
csel
(
o
.
size
>
1
,
string.format
(
"
\\
multicolumn{%d}{|c|}{\\cellcolor{RoyalPurple!25}%s[%d:%d]}"
,
a
-
n
+
1
,
string.upper
(
i
),
a
-
o
.
offset
,
n
-
o
.
offset
),
string.format
(
"
\\
multicolumn{1}{|c|}{\\cellcolor{RoyalPurple!25}%s}"
,
string.upper
(
i
)));
a
=
a
-
s
;
t
=
t
+
1
;
end
end
for
a
=
1
,
e
.
rows
do
local
t
=
""
;
j
=
1
;
k
=
0
;
while
k
<
e
.
cols
do
t
=
t
..
e
.
data
[
a
][
j
].
text
;
if
(
e
.
data
[
a
][
j
].
style
~=
nil
)
then
if
(
e
.
data
[
a
][
j
].
style
==
"td_field"
)
then
k
=
k
+
e
.
data
[
a
][
j
].
flen
;
end
end
k
=
k
+
1
;
if
(
k
~=
e
.
cols
)
then
t
=
t
..
' & '
;
else
t
=
t
..
'
\\\\
'
;
end
j
=
j
+
1
;
end
emit
(
t
);
emit
(
"
\\
hline"
);
end
end
function
cgen_doc_access
(
e
)
if
(
e
==
READ_ONLY
)
then
return
"read-only"
;
elseif
(
e
==
READ_WRITE
)
then
return
"read/write"
;
elseif
(
e
==
WRITE_ONLY
)
then
return
"write-only"
;
else
return
"FIXME!"
;
end
end
cur_reg_no
=
1
;
function
cgen_doc_lx_reg
(
t
)
local
o
=
""
;
local
e
=
""
;
cur_reg_no
=
cur_reg_no
+
1
;
emit
(
"
\\
paragraph*{"
..
t
.
name
..
"}\\vspace{12pt}"
);
emit
(
""
);
local
a
=
htable_new
(
4
,
2
);
a
.
data
[
1
][
1
].
text
=
"{\\bf HW prefix:} "
;
a
.
data
[
2
][
1
].
text
=
"{\\bf HW address:} "
;
a
.
data
[
3
][
1
].
text
=
"{\\bf SW prefix:} "
;
a
.
data
[
4
][
1
].
text
=
"{\\bf SW offset:} "
;
a
.
data
[
1
][
2
].
text
=
string.gsub
(
t
.
full_hdl_prefix
,
"_"
,
"
\\
_"
);
a
.
data
[
2
][
2
].
text
=
string.format
(
"0x%x"
,
t
.
base
);
a
.
data
[
3
][
2
].
text
=
string.gsub
(
string.upper
(
t
.
c_prefix
),
"_"
,
"
\\
_"
);
a
.
data
[
4
][
2
].
text
=
string.format
(
"0x%x"
,
t
.
base
*
(
DATA_BUS_WIDTH
/
8
));
emit
(
"
\\
rowcolors{1}{white}{white}"
);
lx_htable_emit
(
a
);
if
(
t
.
description
~=
nil
)
then
emit
(
"
\\
vspace{12pt}"
);
e
=
string.gsub
(
t
.
description
,
"
\n
"
,
"
\\\\
"
);
e
=
string.gsub
(
e
,
"_"
,
"
\\
_"
);
e
=
string.gsub
(
e
,
"<code>"
,
"
\\
texttt{"
);
e
=
string.gsub
(
e
,
"</code>"
,
"}"
);
emit
(
e
);
end
o
=
"
\\
begin{tabular}{"
;
for
e
=
1
,
8
do
o
=
o
..
">{\\centering\\arraybackslash}p{1.5cm} "
;
end
o
=
o
..
"}"
;
emit
(
""
);
emit
(
"
\\
vspace{12pt}"
);
emit
(
"
\\
noindent"
);
emit
(
'
\\
resizebox{\\textwidth}{!}{'
);
emit
(
o
);
for
e
=
0
,
DATA_BUS_WIDTH
/
8
-
1
do
cgen_doc_lx_fieldtable
(
t
,(
DATA_BUS_WIDTH
/
8
-
1
-
e
)
*
8
);
end
emit
(
"
\\
end{tabular}"
);
emit
(
"}"
);
emit
(
""
);
emit
(
"
\\
begin{itemize}"
);
foreach_subfield
(
t
,
function
(
a
)
emit
(
"
\\
item \\begin{small}"
);
emit
(
"{\\bf "
);
if
(
a
.
c_prefix
==
nil
)
then
emit
(
string.gsub
(
string.upper
(
t
.
c_prefix
),
"_"
,
"
\\
_"
));
else
emit
(
string.gsub
(
string.upper
(
a
.
c_prefix
),
"_"
,
"
\\
_"
));
end
emit
(
"} [\\emph{"
..
cgen_doc_access
(
a
.
access_bus
)
..
"}]: "
..
a
.
name
);
if
(
a
.
description
~=
nil
)
then
emit
(
"
\\\\
"
);
e
=
string.gsub
(
a
.
description
,
"
\n
"
,
"
\\\\
"
);
e
=
string.gsub
(
e
,
"_"
,
"
\\
_"
);
e
=
string.gsub
(
e
,
"<code>"
,
"
\\
texttt{"
);
e
=
string.gsub
(
e
,
"</code>"
,
"}"
);
emit
(
e
);
end
emit
(
"
\\
end{small}"
);
end
);
emit
(
"
\\
end{itemize}"
);
end
cur_mem_no
=
1
;
function
cgen_doc_lx_ram
(
t
)
local
a
=
""
;
emit
(
"
\\
paragraph*{"
..
t
.
name
..
"}\\vspace{12pt}"
);
emit
(
""
);
cur_mem_no
=
cur_mem_no
+
1
;
local
e
=
htable_new
(
11
,
2
);
e
.
data
[
1
][
1
].
text
=
"{\\bf HW prefix:} "
;
e
.
data
[
2
][
1
].
text
=
"{\\bf HW address:} "
;
e
.
data
[
3
][
1
].
text
=
"{\\bf C prefix:} "
;
e
.
data
[
4
][
1
].
text
=
"{\\bf C offset:} "
;
e
.
data
[
5
][
1
].
text
=
"{\\bf Size:} "
;
e
.
data
[
6
][
1
].
text
=
"{\\bf Data width:} "
;
e
.
data
[
7
][
1
].
text
=
"{\\bf Access (bus):} "
;
e
.
data
[
8
][
1
].
text
=
"{\\bf Access (device):} "
;
e
.
data
[
9
][
1
].
text
=
"{\\bf Mirrored:} "
;
e
.
data
[
10
][
1
].
text
=
"{\\bf Byte-addressable:} "
;
e
.
data
[
11
][
1
].
text
=
"{\\bf Peripheral port:} "
;
e
.
data
[
1
][
2
].
text
=
string.lower
(
string.gsub
(
periph
.
hdl_prefix
,
"_"
,
"
\\
_"
)
..
"
\\
_"
..
string.gsub
(
t
.
hdl_prefix
,
"_"
,
"
\\
_"
));
e
.
data
[
2
][
2
].
text
=
string.format
(
"0x%x"
,
t
.
base
);
e
.
data
[
3
][
2
].
text
=
string.upper
(
string.gsub
(
t
.
c_prefix
,
"_"
,
"
\\
_"
));
e
.
data
[
4
][
2
].
text
=
string.format
(
"0x%x"
,
t
.
base
*
(
DATA_BUS_WIDTH
/
8
));
e
.
data
[
5
][
2
].
text
=
t
.
size
..
" "
..
t
.
width
..
"-bit words"
;
e
.
data
[
6
][
2
].
text
=
t
.
width
;
e
.
data
[
7
][
2
].
text
=
cgen_doc_access
(
t
.
access_bus
);
e
.
data
[
8
][
2
].
text
=
cgen_doc_access
(
t
.
access_dev
);
if
(
t
.
byte_select
~=
nil
and
t
.
byte_select
==
true
)
then
e
.
data
[
10
][
2
].
text
=
"yes"
;
else
e
.
data
[
10
][
2
].
text
=
"no"
;
end
if
(
t
.
wrap_bits
~=
nil
and
0
~=
t
.
wrap_bits
)
then
e
.
data
[
9
][
2
].
text
=
math.pow
(
2
,
t
.
wrap_bits
)
..
" times"
;
else
e
.
data
[
9
][
2
].
text
=
"no"
;
end
if
(
t
.
clock
~=
nil
)
then
e
.
data
[
11
][
2
].
text
=
"asynchronous ("
..
t
.
clock
..
")"
;
else
e
.
data
[
11
][
2
].
text
=
"bus-synchronous"
;
end
emit
(
"
\\
begin{small}"
);
lx_htable_emit
(
e
);
emit
(
"
\\
end{small}"
);
if
(
t
.
description
~=
nil
)
then
a
=
string.gsub
(
t
.
description
,
"
\n
"
,
"
\\\\
"
);
a
=
string.gsub
(
a
,
"_"
,
"
\\
_"
);
a
=
string.gsub
(
a
,
"<code>"
,
"
\\
texttt{"
);
a
=
string.gsub
(
a
,
"</code>"
,
"}"
);
emit
(
a
);
end
end
cur_irq_no
=
1
;
function
cgen_doc_lx_irq
(
a
)
local
e
=
""
;
emit
(
"
\\
paragraph*{"
..
a
.
name
..
"}\\vspace{12pt}"
);
cur_irq_no
=
cur_irq_no
+
1
;
local
t
=
htable_new
(
3
,
2
);
t
.
data
[
1
][
1
].
text
=
"{\\bf HW prefix:} "
;
t
.
data
[
2
][
1
].
text
=
"{\\bf C prefix:} "
;
t
.
data
[
3
][
1
].
text
=
"{\\bf Trigger:} "
;
t
.
data
[
1
][
2
].
text
=
string.gsub
(
string.lower
(
periph
.
hdl_prefix
..
"_"
..
a
.
hdl_prefix
),
"_"
,
"
\\
_"
);
t
.
data
[
2
][
2
].
text
=
string.upper
(
string.gsub
(
a
.
c_prefix
,
"_"
,
"
\\
_"
));
local
o
=
{
[
EDGE_RISING
]
=
"rising edge"
;
[
EDGE_FALLING
]
=
"falling edge"
;
[
LEVEL_0
]
=
"low level"
;
[
LEVEL_1
]
=
"high level"
;
};
t
.
data
[
3
][
2
].
text
=
o
[
a
.
trigger
];
emit
(
"
\\
begin{small}"
);
lx_htable_emit
(
t
);
emit
(
"
\\
end{small}"
);
if
(
a
.
description
~=
nil
)
then
emit
(
"
\\
vspace{12pt}"
);
e
=
string.gsub
(
a
.
description
,
"
\n
"
,
"
\\\\
"
);
e
=
string.gsub
(
e
,
"_"
,
"
\\
_"
);
e
=
string.gsub
(
e
,
"<code>"
,
"
\\
texttt{"
);
e
=
string.gsub
(
e
,
"</code>"
,
"}"
);
emit
(
e
);
end
end
function
cgen_generate_latex_documentation
()
cgen_new_snippet
();
emit
(
"
\\
subsubsection{Register description}"
);
foreach_reg
({
TYPE_REG
},
function
(
e
)
if
(
e
.
no_docu
==
nil
or
e
.
no_docu
==
false
)
then
cgen_doc_lx_reg
(
e
);
end
end
);
local
o
=
cgen_get_snippet
();
local
a
=
""
;
if
(
periph
.
ramcount
>
0
)
then
emit
(
"
\\
subsubsection{Memory blocks}"
);
cgen_new_snippet
();
foreach_reg
({
TYPE_RAM
},
function
(
e
)
if
(
e
.
no_docu
==
nil
or
e
.
no_docu
==
false
)
then
cgen_doc_lx_ram
(
e
);
end
end
);
a
=
cgen_get_snippet
();
end
local
t
=
""
;
if
(
periph
.
irqcount
>
0
)
then
cgen_new_snippet
();
emit
(
"
\\
subsubsection{Interrupts}"
);
foreach_reg
({
TYPE_IRQ
},
function
(
e
)
if
(
e
.
no_docu
==
nil
or
e
.
no_docu
==
false
)
then
cgen_doc_lx_irq
(
e
);
end
end
);
t
=
cgen_get_snippet
();
end
cgen_new_snippet
();
cgen_doc_lx_memmap
();
local
e
=
cgen_get_snippet
();
cgen_new_snippet
();
cgen_doc_lx_header_and_toc
();
emit
(
e
);
emit
(
o
);
emit
(
a
);
emit
(
t
);
cgen_write_current_snippet
();
end
function
gen_hdl_field_prefix
(
a
,
e
)
local
t
;
if
(
e
.
hdl_prefix
==
nil
)
then
...
...
@@ -2957,27 +3290,27 @@ e.ports={};
e
.
acklen
=
1
;
e
.
read_code
=
{
va
(
vir
(
"rddata_reg"
,
e
),
e
.
value
);};
end
function
fill_unused_bits
(
o
,
e
)
function
fill_unused_bits
(
i
,
e
)
local
a
=
{};
local
t
=
{};
local
i
=
true
;
local
o
=
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
i
=
false
;
end
if
(
e
.
access_bus
~=
WRITE_ONLY
)
then
o
=
false
;
end
end
);
if
(
i
)
then
if
(
o
)
then
for
e
=
0
,
DATA_BUS_WIDTH
-
1
do
table_join
(
t
,{
va
(
vi
(
o
,
e
),
vundefined
());});
table_join
(
t
,{
va
(
vi
(
i
,
e
),
vundefined
());});
end
return
t
;
end
for
e
=
0
,
DATA_BUS_WIDTH
-
1
do
if
(
a
[
e
]
==
nil
)
then
table_join
(
t
,{
va
(
vi
(
o
,
e
),
vundefined
());});
table_join
(
t
,{
va
(
vi
(
i
,
e
),
vundefined
());});
end
end
return
t
;
...
...
@@ -3100,8 +3433,8 @@ end
function
wbgen_generate_eic
()
if
(
periph
.
irqcount
==
0
)
then
return
;
end
local
t
=
0
;
local
o
=
{};
local
a
=
{[
"__type"
]
=
TYPE_REG
;
local
s
=
{};
local
i
=
{[
"__type"
]
=
TYPE_REG
;
[
"__blockindex"
]
=
1e6
;
[
"align"
]
=
8
;
[
"name"
]
=
"Interrupt disable register"
;
...
...
@@ -3117,7 +3450,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
i
=
{[
"__type"
]
=
TYPE_REG
;
local
a
=
{[
"__type"
]
=
TYPE_REG
;
[
"__blockindex"
]
=
1000001
;
[
"align"
]
=
1
;
[
"name"
]
=
"Interrupt enable register"
;
...
...
@@ -3133,7 +3466,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
s
=
{[
"__type"
]
=
TYPE_REG
;
local
o
=
{[
"__type"
]
=
TYPE_REG
;
[
"__blockindex"
]
=
1000002
;
[
"align"
]
=
1
;
[
"name"
]
=
"Interrupt status register"
;
...
...
@@ -3167,7 +3500,7 @@ local n={["__type"]=TYPE_REG;
foreach_reg
({
TYPE_IRQ
},
function
(
e
)
e
.
index
=
t
;
t
=
t
+
1
;
table.insert
(
o
,{[
"index"
]
=
e
.
index
;[
"trigger"
]
=
e
.
trigger
;});
table.insert
(
s
,{[
"index"
]
=
e
.
index
;[
"trigger"
]
=
e
.
trigger
;});
fix_prefix
(
e
);
local
t
=
{
[
"__blockindex"
]
=
e
.
index
;
...
...
@@ -3180,7 +3513,7 @@ local t={
[
"access_bus"
]
=
READ_WRITE
;
[
"access_dev"
]
=
READ_WRITE
;
};
local
o
=
{
local
s
=
{
[
"__blockindex"
]
=
e
.
index
;
[
"__type"
]
=
TYPE_FIELD
;
[
"type"
]
=
BIT
;
...
...
@@ -3222,18 +3555,18 @@ end
if
(
e
.
mask_line
==
true
)
then
table_join
(
e
.
ports
,{
port
(
BIT
,
0
,
"out"
,
e
.
full_prefix
..
"_mask_o"
);});
end
table.insert
(
a
,
r
);
table.insert
(
s
,
t
);
table.insert
(
i
,
r
);
table.insert
(
o
,
t
);
table.insert
(
n
,
h
);
table.insert
(
i
,
o
);
table.insert
(
a
,
s
);
end
);
add_global_signals
({
signal
(
SLV
,
periph
.
irqcount
,
"irq_inputs_vector_int"
);
});
table.insert
(
periph
,
a
);
table.insert
(
periph
,
i
);
table.insert
(
periph
,
a
);
table.insert
(
periph
,
n
);
table.insert
(
periph
,
s
);
table.insert
(
periph
,
o
);
local
e
=
{
vgm
(
"g_num_interrupts"
,
periph
.
irqcount
);
vpm
(
"clk_i"
,
"clk_sys_i"
);
vpm
(
"rst_n_i"
,
"rst_n_i"
);
...
...
@@ -3250,7 +3583,7 @@ vpm("reg_isr_wr_stb_i","eic_isr_write_int");
vpm
(
"wb_irq_o"
,
"wb_int_o"
);
};
local
a
;
for
o
,
t
in
ipairs
(
o
)
do
for
o
,
t
in
ipairs
(
s
)
do
table_join
(
e
,{
vgm
(
string.format
(
"g_irq%02x_mode"
,
t
.
index
),
t
.
trigger
)});
a
=
o
;
end
...
...
@@ -3430,7 +3763,7 @@ local s={
[
"hdl_prefix"
]
=
e
.
hdl_prefix
..
"_CSR"
;
[
"no_std_regbank"
]
=
true
;
};
function
gen_fifo_csr_field
(
d
,
n
,
t
,
r
,
h
,
o
,
a
,
i
)
function
gen_fifo_csr_field
(
d
,
n
,
t
,
a
,
h
,
o
,
r
,
i
)
print
(
"GenCSR Field "
..
t
);
if
(
e
.
flags_bus
==
nil
)
then
return
;
...
...
@@ -3439,12 +3772,12 @@ if inset(d,e.flags_bus)then
local
t
=
{
[
"__type"
]
=
TYPE_FIELD
;
[
"name"
]
=
t
;
[
"description"
]
=
r
;
[
"description"
]
=
a
;
[
"access_bus"
]
=
READ_ONLY
;
[
"access_dev"
]
=
WRITE_ONLY
;
[
"type"
]
=
o
;
[
"size"
]
=
h
;
[
"offset"
]
=
a
;
[
"offset"
]
=
r
;
[
"c_prefix"
]
=
n
;
[
"hdl_prefix"
]
=
n
;
[
"signals"
]
=
{};
...
...
@@ -3639,42 +3972,42 @@ gen_pipelined_wb_signals(e);
foreach_reg
(
ALL_REG_TYPES
,
function
(
e
)
gen_abstract_code
(
e
);
end
);
local
o
=
{};
local
i
=
{};
local
n
=
{};
local
i
=
{};
local
o
=
{};
foreach_field
(
function
(
e
,
t
)
table_join
(
o
,
e
.
reset_code_main
);
table_join
(
n
,
e
.
reset_code_main
);
end
);
foreach_reg
(
ALL_REG_TYPES
,
function
(
e
)
table_join
(
o
,
e
.
reset_code_main
);
table_join
(
n
,
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
(
n
,
e
.
ackgen_code_pre
);
table_join
(
o
,
e
.
ackgen_code_pre
);
end
);
table_join
(
i
,
e
.
ackgen_code
);
table_join
(
n
,
e
.
ackgen_code_pre
);
table_join
(
o
,
e
.
ackgen_code_pre
);
end
);
local
e
=
{};
foreach_reg
({
TYPE_REG
},
function
(
t
)
local
n
=
find_max
(
t
,
"acklen"
);
local
a
=
{};
local
i
=
find_max
(
t
,
"acklen"
);
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
(
o
,
t
.
write_code
);
table_join
(
a
,
t
.
read_code
);
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
n
=
fill_unused_bits
(
"rddata_reg"
,
t
);
table_join
(
a
,
t
.
write_code
);
table_join
(
o
,
t
.
read_code
);
local
a
=
{
vif
(
vequal
(
"wb_we_i"
,
1
),{
o
,
});
a
,
i
});
o
,
n
};
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
(
vi
(
"ack_sreg"
,
math.max
(
i
-
1
,
0
)),
1
);});
table_join
(
a
,{
va
(
"ack_in_progress"
,
1
);});
end
if
(
regbank_address_bits
>
0
)
then
...
...
@@ -3731,14 +4064,14 @@ vreset(0,{
va
(
"ack_sreg"
,
0
);
va
(
"ack_in_progress"
,
0
);
va
(
"rddata_reg"
,
0
);
o
n
});
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
);},
n
);
vif
(
vequal
(
vi
(
"ack_sreg"
,
0
),
1
),{
i
;
va
(
"ack_in_progress"
,
0
);},
o
);
},{
e
});
...
...
@@ -3747,20 +4080,20 @@ e
};
if
(
periph
.
ramcount
>
0
)
then
if
(
not
options
.
register_data_output
)
then
local
a
=
{
"rddata_reg"
,
"rwaddr_reg"
};
local
t
=
{};
local
o
=
{
vswitch
(
vi
(
"rwaddr_reg"
,
address_bus_width
-
1
,
address_bus_width
-
address_bus_select_bits
),
t
);};
local
o
=
{
vcomment
(
"Data output multiplexer process"
);
vcombprocess
(
a
,
o
);};
local
t
=
{
"rddata_reg"
,
"rwaddr_reg"
};
local
a
=
{};
local
o
=
{
vswitch
(
vi
(
"rwaddr_reg"
,
address_bus_width
-
1
,
address_bus_width
-
address_bus_select_bits
),
a
);};
local
o
=
{
vcomment
(
"Data output multiplexer process"
);
vcombprocess
(
t
,
o
);};
foreach_reg
({
TYPE_RAM
},
function
(
e
)
table.insert
(
a
,
e
.
full_prefix
..
"_rddata_int"
);
local
a
=
{
va
(
vi
(
"wb_dat_o"
,
e
.
width
-
1
,
0
),
e
.
full_prefix
..
"_rddata_int"
);};
table.insert
(
t
,
e
.
full_prefix
..
"_rddata_int"
);
local
t
=
{
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_dat_o"
,
DATA_BUS_WIDTH
-
1
,
e
.
width
),
0
);});
table_join
(
t
,{
va
(
vi
(
"wb_dat_o"
,
DATA_BUS_WIDTH
-
1
,
e
.
width
),
0
);});
end
table_join
(
t
,{
vcase
(
e
.
select_bits
,
a
);});
table_join
(
a
,{
vcase
(
e
.
select_bits
,
t
);});
end
);
table.insert
(
a
,
"wb_adr_i"
);
table_join
(
t
,{
vcasedefault
(
va
(
"wb_dat_o"
,
"rddata_reg"
));});
table.insert
(
t
,
"wb_adr_i"
);
table_join
(
a
,{
vcasedefault
(
va
(
"wb_dat_o"
,
"rddata_reg"
));});
table_join
(
e
,
o
);
end
local
a
=
{
"wb_adr_i"
,
"rd_int"
,
"wr_int"
};
...
...
@@ -3814,7 +4147,7 @@ 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
-f, --docformat=FORMAT Write documentation for texinfo or HTML (defaults to HTML)
-f, --docformat=FORMAT Write documentation for
latex,
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
...
...
@@ -3941,7 +4274,10 @@ end
if
(
options
.
output_doc_file
~=
nil
)
then
cgen_generate_init
(
options
.
output_doc_file
);
if
(
options
.
doc_format
==
"html"
)
then
print
(
"gen html"
);
cgen_generate_documentation
();
elseif
(
options
.
doc_format
==
"latex"
)
then
cgen_generate_latex_documentation
();
else
cgen_generate_texinfo_documentation
();
end
...
...
wbgen_main.lua
View file @
f4b155be
...
...
@@ -36,7 +36,7 @@ local usage_string = [[slave Wishbone generator
local
commands_string
=
[[options:
-C, --co=FILE Write the slave's generated C header file to FILE
-f, --docformat=FORMAT Write documentation for texinfo or HTML (defaults to HTML)
-f, --docformat=FORMAT Write documentation for
latex,
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
...
...
@@ -209,8 +209,11 @@ if(options.output_doc_file ~= nil) then
cgen_generate_init
(
options
.
output_doc_file
);
if
(
options
.
doc_format
==
"html"
)
then
print
(
"gen html"
);
cgen_generate_documentation
();
else
elseif
(
options
.
doc_format
==
"latex"
)
then
cgen_generate_latex_documentation
();
else
cgen_generate_texinfo_documentation
();
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment