URL
https://opencores.org/ocsvn/radiohdl/radiohdl/trunk
Subversion Repositories radiohdl
[/] [radiohdl/] [trunk/] [core/] [generate_qsys] - Rev 4
Compare with Previous | Blame | View Log
#!/usr/bin/env python3
###############################################################################
#
# Copyright (C) 2015
# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
"""
Purpose:
. Generate an Altera QSYS file from a base QSYS file and user supplied list of regs.
Usage:
. python generate_qsys.py
"""
from common import *
def _to_element_str(reg_name, reg_base_addr):
"""
Returns a template XML 'element' filled in with reg_name and reg_base_addr.
"""
ELEMENT_TEMPLATE = """
element HDL_REG_NAME.mem
{
datum baseAddress
{
value = HDL_REG_BASE_ADDR;
type = "long";
}
datum _sortIndex
{
value = "8";
type = "int";
}
datum sopceditor_expanded
{
value = "0";
type = "boolean";
}
}
"""
return ELEMENT_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_BASE_ADDR', str(reg_base_addr))
def _to_interface_str(reg_name):
"""
Returns a template XML 'interface' filled in with reg_name.
"""
INTERFACE_TEMPLATE = """
<interface
name="HDL_REG_NAME_reset"
internal="HDL_REG_NAME.reset"
type="conduit"
dir="end" />
<interface
name="HDL_REG_NAME_clk"
internal="HDL_REG_NAME.clk"
type="conduit"
dir="end" />
<interface
name="HDL_REG_NAME_address"
internal="HDL_REG_NAME.address"
type="conduit"
dir="end" />
<interface
name="HDL_REG_NAME_write"
internal="HDL_REG_NAME.write"
type="conduit"
dir="end" />
<interface
name="HDL_REG_NAME_writedata"
internal="HDL_REG_NAME.writedata"
type="conduit"
dir="end" />
<interface
name="HDL_REG_NAME_read"
internal="HDL_REG_NAME.read"
type="conduit"
dir="end" />
<interface
name="HDL_REG_NAME_readdata"
internal="HDL_REG_NAME.readdata"
type="conduit"
dir="end" />
"""
return INTERFACE_TEMPLATE.replace('HDL_REG_NAME', reg_name)
def _append_to_modules_mid_str(modules_mid_str, reg_name, reg_base_addr, reg_end_addr):
"""
The modules_mid section contains one line (dataSlaveMapParam) for all start- and end addresses.
Append the start and end address of our register to this line.
"""
DATASLAVEMAPPARAM_TEMPLATE = "<slave name='HDL_REG_NAME.mem' start='HDL_REG_BASE_ADDR' end='HDL_REG_END_ADDR' />"
return modules_mid_str + DATASLAVEMAPPARAM_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_BASE_ADDR', str(reg_base_addr)).replace('HDL_REG_END_ADDR', str(reg_end_addr))
def _to_module_str(reg_name, reg_addr_w):
"""
Returns a template XML 'module' filled in with reg_name and reg_addr_w.
"""
MODULE_TEMPLATE = """
<module kind="avs_common_mm" version="1.0" enabled="1" name="HDL_REG_NAME">
<parameter name="g_adr_w" value="HDL_REG_ADDR_W" />
<parameter name="g_dat_w" value="32" />
<parameter name="AUTO_SYSTEM_CLOCK_RATE" value="25000000" />
</module>
"""
return MODULE_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_ADDR_W', str(reg_addr_w))
def _to_connection_str(reg_name, reg_base_addr):
"""
Returns a template XML 'connection' filled in with reg_name and reg_base_addr.
"""
CONNECTION_TEMPLATE = """
<connection
kind="reset"
version="11.1"
start="cpu_0.jtag_debug_module_reset"
end="HDL_REG_NAME.system_reset" />
<connection
kind="avalon"
version="11.1"
start="cpu_0.data_master"
end="HDL_REG_NAME.mem">
<parameter name="arbitrationPriority" value="1" />
<parameter name="baseAddress" value="HDL_REG_BASE_ADDR" />
</connection>
<connection
kind="reset"
version="11.1"
start="clk_input.clk_reset"
end="HDL_REG_NAME.system_reset" />
<connection
kind="clock"
version="11.1"
start="clk_input.clk"
end="HDL_REG_NAME.system" />
"""
return CONNECTION_TEMPLATE.replace('HDL_REG_NAME', reg_name).replace('HDL_REG_BASE_ADDR', str(reg_base_addr))
def generate_qsys(input_qsys, regs, output_filename):
"""
Creates an XML QSYS file (output_filename) from a base QSYS and a user-supplied list of registers to add (regs).
. regs = [ (reg_name, reg_base_addr, reg_span), .. ]
"""
# Read the base QSYS contents into a string
with open (input_qsys, "r") as base_qsys_file:
data=base_qsys_file.read()
# We'll split the base QSYS string up in 5 sections.
# . Note that string.split() throws away the delimiter so we'll restore those later.
elements = data.split(']]></parameter>', 1)[0]
parameters = data.split(']]></parameter>', 1)[1].split('</instanceScript>', 1)[0]
interfaces = data.split(']]></parameter>', 1)[1].split('</instanceScript>', 1)[1].split('<module', 1)[0]
modules_head = data.split(']]></parameter>', 1)[1].split('</instanceScript>', 1)[1].split('<module', 1)[1].split('<connection', 1)[0].split('"dataSlaveMapParam">')[0]
modules_mid = data.split(']]></parameter>', 1)[1].split('</instanceScript>', 1)[1].split('<module', 1)[1].split('<connection', 1)[0].split('"dataSlaveMapParam">')[1].split('</address-map>]]></parameter>',1)[0]
modules_tail = data.split(']]></parameter>', 1)[1].split('</instanceScript>', 1)[1].split('<module', 1)[1].split('<connection', 1)[0].split('"dataSlaveMapParam">')[1].split('</address-map>]]></parameter>',1)[1]
connections = data.split(']]></parameter>', 1)[1].split('</instanceScript>', 1)[1].split('<module', 1)[1].split('<connection', 1)[1].split('</system', 1)[0]
# Now we'll append our own XML strings to each section.
for reg_name, reg_base_addr, reg_addr_w in regs:
# Determine the end address of this register
reg_span = ceil_log2(reg_addr_w)
reg_end_addr = reg_base_addr + reg_span
# Add strings to the sections
elements += _to_element_str(reg_name, reg_base_addr)
parameters = parameters
interfaces += _to_interface_str(reg_name)
modules_head = modules_head
modules_mid = _append_to_modules_mid_str(modules_mid, reg_name, reg_base_addr, reg_end_addr)
modules_tail += _to_module_str(reg_name, reg_addr_w)
connections += _to_connection_str(reg_name, reg_base_addr)
# Re-assemble the sections into one string (add the delimiters that were thrown away by split())
qsys_str = elements + \
']]></parameter>\n' + \
parameters + \
'</instanceScript>\n' + \
interfaces + \
'<module\n' + \
modules_head + \
'"dataSlaveMapParam">' + \
modules_mid + \
'</address-map>]]></parameter>\n' + \
modules_tail + \
'<connection\n' + \
connections + \
'</system>\n'
# Write the QSYS string to the output_file.
output_file = open(output_filename, "w")
output_file.write(qsys_str)
output_file.close()
################################################################################
# Example main on execution of this file
################################################################################
if __name__ == '__main__':
base_qsys_path = 'qsys_input.qsys'
regs = [('reg_my_peripheral', 16384, 3), ('reg_another_peripheral', 17152, 6)]
generate_qsys(base_qsys_path, regs, 'qsys_generated.qsys')