Efinix: improve ifacewriter + misc
This commit is contained in:
parent
45961f733b
commit
a08c5201ad
|
@ -287,6 +287,8 @@ class EfinityToolchain():
|
||||||
run = True,
|
run = True,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
|
|
||||||
|
self.ifacewriter.set_build_params(platform, build_name)
|
||||||
|
|
||||||
# Create build directory
|
# Create build directory
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.makedirs(build_dir, exist_ok=True)
|
os.makedirs(build_dir, exist_ok=True)
|
||||||
|
@ -342,7 +344,8 @@ class EfinityToolchain():
|
||||||
|
|
||||||
# DDR doesn't have Python API so we need to configure it
|
# DDR doesn't have Python API so we need to configure it
|
||||||
# directly in the peri.xml file
|
# directly in the peri.xml file
|
||||||
# self.ifacewriter.add_ddr_xml(build_name)
|
if self.ifacewriter.xml_blocks:
|
||||||
|
self.ifacewriter.generate_xml_blocks()
|
||||||
|
|
||||||
# Run
|
# Run
|
||||||
if run:
|
if run:
|
||||||
|
|
|
@ -16,11 +16,72 @@ class InterfaceWriter():
|
||||||
def __init__(self, efinity_path):
|
def __init__(self, efinity_path):
|
||||||
self.efinity_path = efinity_path
|
self.efinity_path = efinity_path
|
||||||
self.blocks = []
|
self.blocks = []
|
||||||
|
self.xml_blocks = []
|
||||||
|
self.filename = ''
|
||||||
|
self.platform = None
|
||||||
|
|
||||||
def add_ddr_xml(self, filename):
|
def set_build_params(self, platform, build_name):
|
||||||
|
self.filename = build_name
|
||||||
|
self.platform = platform
|
||||||
|
|
||||||
|
def generate_xml_blocks(self):
|
||||||
et.register_namespace('efxpt', "http://www.efinixinc.com/peri_design_db")
|
et.register_namespace('efxpt', "http://www.efinixinc.com/peri_design_db")
|
||||||
tree = et.parse(filename + '.peri.xml')
|
tree = et.parse(self.filename + '.peri.xml')
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
|
|
||||||
|
for block in self.xml_blocks:
|
||||||
|
if block['type'] == 'DDR':
|
||||||
|
self.add_ddr_xml(root, block)
|
||||||
|
if block['type'] == 'LVDS':
|
||||||
|
self.add_ddr_lvds(root, block)
|
||||||
|
|
||||||
|
xml_string = et.tostring(root, 'utf-8')
|
||||||
|
reparsed = expatbuilder.parseString(xml_string, False)
|
||||||
|
print_string = reparsed.toprettyxml(indent=" ")
|
||||||
|
|
||||||
|
# Remove lines with only whitespaces. Not sure why they are here
|
||||||
|
print_string = os.linesep.join([s for s in print_string.splitlines() if s.strip()])
|
||||||
|
|
||||||
|
tools.write_to_file("{}.peri.xml".format(self.filename), print_string)
|
||||||
|
|
||||||
|
def add_ddr_lvds(self, root, params):
|
||||||
|
lvds_info = root.find('efxpt:lvds_info', namespaces)
|
||||||
|
if params['mode'] == 'OUTPUT':
|
||||||
|
dir = 'tx'
|
||||||
|
mode = 'out'
|
||||||
|
else:
|
||||||
|
dir = 'rx'
|
||||||
|
mode = 'in'
|
||||||
|
|
||||||
|
pad = self.platform.parser.get_gpio_instance_from_pin(params['location'][0])
|
||||||
|
pad = pad.replace('TXP', 'TX')
|
||||||
|
pad = pad.replace('TXN', 'TX')
|
||||||
|
pad = pad.replace('RXP', 'RX')
|
||||||
|
pad = pad.replace('RXN', 'RX')
|
||||||
|
# Sometimes there is an extra identifier at the end
|
||||||
|
# TODO: do a better parser
|
||||||
|
if pad.count('_') == 2:
|
||||||
|
pad = pad.rsplit('_', 1)[0]
|
||||||
|
|
||||||
|
lvds = et.SubElement(lvds_info, 'efxpt:lvds',
|
||||||
|
name = params['name'],
|
||||||
|
lvds_def = pad,
|
||||||
|
ops_type = dir)
|
||||||
|
|
||||||
|
et.SubElement(lvds, 'efxpt:ltx_info', pll_instance = '',
|
||||||
|
fast_clock_name = '{}'.format(params['fast_clk']),
|
||||||
|
slow_clock_name = '{}'.format(params['slow_clk']),
|
||||||
|
reset_name = '',
|
||||||
|
out_bname = '{}'.format(params['name']),
|
||||||
|
oe_name = '',
|
||||||
|
clock_div = '1',
|
||||||
|
mode = '{}'.format(mode),
|
||||||
|
serialization = '{}'.format(params['serialisation']),
|
||||||
|
reduced_swing = 'false',
|
||||||
|
load = '3')
|
||||||
|
|
||||||
|
|
||||||
|
def add_ddr_xml(self, root, params):
|
||||||
ddr_info = root.find('efxpt:ddr_info', namespaces)
|
ddr_info = root.find('efxpt:ddr_info', namespaces)
|
||||||
|
|
||||||
ddr = et.SubElement(ddr_info, 'efxpt:ddr',
|
ddr = et.SubElement(ddr_info, 'efxpt:ddr',
|
||||||
|
@ -135,15 +196,6 @@ class InterfaceWriter():
|
||||||
et.SubElement(cs_gate_delay, 'efxpt:param', name='GATE_C_DLY', value= '3', value_type='int')
|
et.SubElement(cs_gate_delay, 'efxpt:param', name='GATE_C_DLY', value= '3', value_type='int')
|
||||||
et.SubElement(cs_gate_delay, 'efxpt:param', name='GATE_F_DLY', value= '0', value_type='int')
|
et.SubElement(cs_gate_delay, 'efxpt:param', name='GATE_F_DLY', value= '0', value_type='int')
|
||||||
|
|
||||||
xml_string = et.tostring(root, 'utf-8')
|
|
||||||
reparsed = expatbuilder.parseString(xml_string, False)
|
|
||||||
print_string = reparsed.toprettyxml(indent=" ")
|
|
||||||
|
|
||||||
# Remove lines with only whitespaces. Not sure why they are here
|
|
||||||
print_string = os.linesep.join([s for s in print_string.splitlines() if s.strip()])
|
|
||||||
|
|
||||||
tools.write_to_file("{}.peri.xml".format(filename), print_string)
|
|
||||||
|
|
||||||
def header(self, build_name, partnumber):
|
def header(self, build_name, partnumber):
|
||||||
header = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision()
|
header = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision()
|
||||||
header += """
|
header += """
|
||||||
|
@ -185,8 +237,16 @@ design.create('{2}', '{3}', './../gateware', overwrite=True)
|
||||||
mode = block['mode']
|
mode = block['mode']
|
||||||
cmd = ''
|
cmd = ''
|
||||||
|
|
||||||
|
if mode == 'INOUT':
|
||||||
# TODO: {'type': 'GPIO', 'mode': 'OUTPUT', 'location': 'U16', 'size': 4, 'in_reg': 'DDIO_RESYNC', 'out_clk_pin': '', 'is_inclk_inverted': False, 'name': 'auto_ethtx_tx_data_d1', 'name_d2': 'auto_ethtx_tx_data_d2'}
|
if len(block['location']) == 1:
|
||||||
|
cmd += 'design.create_inout_gpio("{}")\n'.format(name)
|
||||||
|
cmd += 'design.assign_pkg_pin("{}","{}")\n'.format(name, block['location'][0])
|
||||||
|
else:
|
||||||
|
cmd += 'design.create_inout_gpio("{}",{},0)\n'.format(name, block['size']-1)
|
||||||
|
for i, pad in enumerate(block['location']):
|
||||||
|
cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad)
|
||||||
|
cmd += '\n'
|
||||||
|
return cmd
|
||||||
|
|
||||||
if mode == 'INPUT':
|
if mode == 'INPUT':
|
||||||
if len(block['location']) == 1:
|
if len(block['location']) == 1:
|
||||||
|
@ -198,7 +258,7 @@ design.create('{2}', '{3}', './../gateware', overwrite=True)
|
||||||
cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad)
|
cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad)
|
||||||
if 'in_reg' in block:
|
if 'in_reg' in block:
|
||||||
cmd += 'design.set_property("{}","IN_REG","{}")\n'.format(name, block['in_reg'])
|
cmd += 'design.set_property("{}","IN_REG","{}")\n'.format(name, block['in_reg'])
|
||||||
cmd += 'design.set_property("{}","IN_CLK_PIN","{}")\n\n'.format(name, block['in_clk_pin'])
|
cmd += 'design.set_property("{}","IN_CLK_PIN","{}")\n'.format(name, block['in_clk_pin'])
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
if mode == 'OUTPUT':
|
if mode == 'OUTPUT':
|
||||||
|
@ -262,20 +322,26 @@ design.create('{2}', '{3}', './../gateware', overwrite=True)
|
||||||
|
|
||||||
cmd += 'design.set_property("{}", pll_config, block_type="PLL")\n\n'.format(name)
|
cmd += 'design.set_property("{}", pll_config, block_type="PLL")\n\n'.format(name)
|
||||||
|
|
||||||
|
for i, clock in enumerate(block['clk_out']):
|
||||||
|
cmd += 'design.set_property("{}","CLKOUT{}_PHASE","{}","PLL")\n'.format(name, i, clock[2])
|
||||||
|
|
||||||
cmd += 'target_freq = {\n'
|
cmd += 'target_freq = {\n'
|
||||||
for i, clock in enumerate(block['clk_out']):
|
for i, clock in enumerate(block['clk_out']):
|
||||||
cmd += ' "CLKOUT{}_FREQ": "{}",\n'.format(i, clock[1] / 1e6)
|
cmd += ' "CLKOUT{}_FREQ": "{}",\n'.format(i, clock[1] / 1e6)
|
||||||
cmd += ' "CLKOUT{}_PHASE": "{}",\n'.format(i, clock[2])
|
|
||||||
cmd += '}\n'
|
cmd += '}\n'
|
||||||
cmd += 'calc_result = design.auto_calc_pll_clock("{}", target_freq)\n\n'.format(name)
|
cmd += 'calc_result = design.auto_calc_pll_clock("{}", target_freq)\n'.format(name)
|
||||||
|
|
||||||
|
if 'extra' in block:
|
||||||
|
cmd += block['extra']
|
||||||
|
cmd += '\n'
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
cmd += 'print("#### {} ####")\n'.format(name)
|
cmd += 'print("#### {} ####")\n'.format(name)
|
||||||
cmd += 'clksrc_info = design.trace_ref_clock("{}", block_type="PLL")\n'.format(name)
|
cmd += 'clksrc_info = design.trace_ref_clock("{}", block_type="PLL")\n'.format(name)
|
||||||
cmd += 'pprint.pprint(clksrc_info)\n'
|
cmd += 'pprint.pprint(clksrc_info)\n'
|
||||||
cmd += 'clock_source_prop = ["REFCLK_SOURCE", "CORE_CLK_PIN", "EXT_CLK", "CLKOUT0_EN", "CLKOUT1_EN","REFCLK_FREQ", "RESOURCE"]\n'
|
cmd += 'clock_source_prop = ["REFCLK_SOURCE", "CORE_CLK_PIN", "EXT_CLK", "CLKOUT1_EN", "CLKOUT2_EN","REFCLK_FREQ", "RESOURCE"]\n'
|
||||||
cmd += 'clock_source_prop += ["CLKOUT0_FREQ", "CLKOUT1_FREQ", "CLKOUT2_FREQ"]\n'
|
cmd += 'clock_source_prop += ["CLKOUT0_FREQ", "CLKOUT1_FREQ", "CLKOUT2_FREQ"]\n'
|
||||||
|
cmd += 'clock_source_prop += ["CLKOUT0_PHASE", "CLKOUT1_PHASE", "CLKOUT2_PHASE"]\n'
|
||||||
cmd += 'prop_map = design.get_property("{}", clock_source_prop, block_type="PLL")\n'.format(name)
|
cmd += 'prop_map = design.get_property("{}", clock_source_prop, block_type="PLL")\n'.format(name)
|
||||||
cmd += 'pprint.pprint(prop_map)\n'
|
cmd += 'pprint.pprint(prop_map)\n'
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from litex.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from litex.soc.cores.clock.common import *
|
from litex.soc.cores.clock.common import *
|
||||||
|
|
||||||
from litex.build.efinix import EfinixDbParser
|
|
||||||
|
|
||||||
class Open(Signal): pass
|
class Open(Signal): pass
|
||||||
|
|
||||||
#TODO: do somthing else
|
#TODO: do somthing else
|
||||||
|
@ -61,16 +59,15 @@ class TRIONPLL(Module):
|
||||||
# If clkin has a pin number, PLL clock input is EXTERNAL
|
# If clkin has a pin number, PLL clock input is EXTERNAL
|
||||||
if self.platform.get_pin_location(clkin):
|
if self.platform.get_pin_location(clkin):
|
||||||
|
|
||||||
pad_name = self.platform.get_pin_location(clkin)
|
pad_name = self.platform.get_pin_location(clkin)[0]
|
||||||
self.platform.delete(clkin)
|
self.platform.delete(clkin)
|
||||||
|
|
||||||
#tpl = "create_clock -name {clk} -period {period} [get_ports {{{clk}}}]"
|
#tpl = "create_clock -name {clk} -period {period} [get_ports {{{clk}}}]"
|
||||||
#sdc = self.platform.toolchain.additional_sdc_commands
|
#sdc = self.platform.toolchain.additional_sdc_commands
|
||||||
#sdc.append(tpl.format(clk=block['input_clock_name'], period=1/freq))
|
#sdc.append(tpl.format(clk=block['input_clock_name'], period=1/freq))
|
||||||
|
|
||||||
parser = EfinixDbParser(self.platform.efinity_path, self.platform.device)
|
|
||||||
try:
|
try:
|
||||||
(pll_res, clock_no) = parser.get_pll_inst_from_pin(pad_name)
|
(pll_res, clock_no) = self.platform.parser.get_pll_inst_from_pin(pad_name)
|
||||||
except:
|
except:
|
||||||
self.logger.error("Cannot find a pll with {} as input".format(pad_name))
|
self.logger.error("Cannot find a pll with {} as input".format(pad_name))
|
||||||
quit()
|
quit()
|
||||||
|
@ -115,6 +112,10 @@ class TRIONPLL(Module):
|
||||||
block = self.platform.toolchain.ifacewriter.get_block(self.pll_name)
|
block = self.platform.toolchain.ifacewriter.get_block(self.pll_name)
|
||||||
block['clk_out'].append([clk_out_name, freq, phase, margin])
|
block['clk_out'].append([clk_out_name, freq, phase, margin])
|
||||||
|
|
||||||
|
def extra(self, extra):
|
||||||
|
block = self.platform.toolchain.ifacewriter.get_block(self.pll_name)
|
||||||
|
block['extra'] = extra
|
||||||
|
|
||||||
def compute_config(self):
|
def compute_config(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue