OpenCores
URL https://opencores.org/ocsvn/radiohdl/radiohdl/trunk

Subversion Repositories radiohdl

[/] [radiohdl/] [trunk/] [base/] [generate_qsys] - Rev 2

Compare with Previous | Blame | View Log

###############################################################################
#
# 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 RADIOHDL_REG_NAME.mem
   {
      datum baseAddress
      {
         value = RADIOHDL_REG_BASE_ADDR;
         type = "long";
       }
      datum _sortIndex
      {
         value = "8";
         type = "int";
      }
      datum sopceditor_expanded
      {
         value = "0";
         type = "boolean";
      }
   }
    """
    return ELEMENT_TEMPLATE.replace('RADIOHDL_REG_NAME', reg_name).replace('RADIOHDL_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="RADIOHDL_REG_NAME_reset"
   internal="RADIOHDL_REG_NAME.reset"
   type="conduit"
   dir="end" />
 <interface
   name="RADIOHDL_REG_NAME_clk"
   internal="RADIOHDL_REG_NAME.clk"
   type="conduit"
   dir="end" />
 <interface
   name="RADIOHDL_REG_NAME_address"
   internal="RADIOHDL_REG_NAME.address"
   type="conduit"
   dir="end" />
 <interface
   name="RADIOHDL_REG_NAME_write"
   internal="RADIOHDL_REG_NAME.write"
   type="conduit"
   dir="end" />
 <interface
   name="RADIOHDL_REG_NAME_writedata"
   internal="RADIOHDL_REG_NAME.writedata"
   type="conduit"
   dir="end" />
 <interface
   name="RADIOHDL_REG_NAME_read"
   internal="RADIOHDL_REG_NAME.read"
   type="conduit"
   dir="end" />
 <interface
   name="RADIOHDL_REG_NAME_readdata"
   internal="RADIOHDL_REG_NAME.readdata"
   type="conduit"
   dir="end" />
    """
    return INTERFACE_TEMPLATE.replace('RADIOHDL_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='RADIOHDL_REG_NAME.mem' start='RADIOHDL_REG_BASE_ADDR' end='RADIOHDL_REG_END_ADDR' />"
    return modules_mid_str + DATASLAVEMAPPARAM_TEMPLATE.replace('RADIOHDL_REG_NAME', reg_name).replace('RADIOHDL_REG_BASE_ADDR', str(reg_base_addr)).replace('RADIOHDL_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="RADIOHDL_REG_NAME">
  <parameter name="g_adr_w" value="RADIOHDL_REG_ADDR_W" />
  <parameter name="g_dat_w" value="32" />
  <parameter name="AUTO_SYSTEM_CLOCK_RATE" value="25000000" />
 </module>

    """
    return MODULE_TEMPLATE.replace('RADIOHDL_REG_NAME', reg_name).replace('RADIOHDL_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="RADIOHDL_REG_NAME.system_reset" />
 <connection
   kind="avalon"
   version="11.1"
   start="cpu_0.data_master"
   end="RADIOHDL_REG_NAME.mem">
  <parameter name="arbitrationPriority" value="1" />
  <parameter name="baseAddress" value="RADIOHDL_REG_BASE_ADDR" />
 </connection>
 <connection
   kind="reset"
   version="11.1"
   start="clk_input.clk_reset"
   end="RADIOHDL_REG_NAME.system_reset" />
 <connection
   kind="clock"
   version="11.1"
   start="clk_input.clk"
   end="RADIOHDL_REG_NAME.system" />
    """
    return CONNECTION_TEMPLATE.replace('RADIOHDL_REG_NAME', reg_name).replace('RADIOHDL_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')

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2019 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.