Efinix: improve ifacewriter + misc
This commit is contained in:
parent
45961f733b
commit
a08c5201ad
|
@ -287,6 +287,8 @@ class EfinityToolchain():
|
|||
run = True,
|
||||
**kwargs):
|
||||
|
||||
self.ifacewriter.set_build_params(platform, build_name)
|
||||
|
||||
# Create build directory
|
||||
cwd = os.getcwd()
|
||||
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
|
||||
# directly in the peri.xml file
|
||||
# self.ifacewriter.add_ddr_xml(build_name)
|
||||
if self.ifacewriter.xml_blocks:
|
||||
self.ifacewriter.generate_xml_blocks()
|
||||
|
||||
# Run
|
||||
if run:
|
||||
|
|
|
@ -16,11 +16,72 @@ class InterfaceWriter():
|
|||
def __init__(self, efinity_path):
|
||||
self.efinity_path = efinity_path
|
||||
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")
|
||||
tree = et.parse(filename + '.peri.xml')
|
||||
tree = et.parse(self.filename + '.peri.xml')
|
||||
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 = 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_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):
|
||||
header = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision()
|
||||
header += """
|
||||
|
@ -185,8 +237,16 @@ design.create('{2}', '{3}', './../gateware', overwrite=True)
|
|||
mode = block['mode']
|
||||
cmd = ''
|
||||
|
||||
|
||||
# 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 mode == 'INOUT':
|
||||
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 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)
|
||||
if 'in_reg' in block:
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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'
|
||||
for i, clock in enumerate(block['clk_out']):
|
||||
cmd += ' "CLKOUT{}_FREQ": "{}",\n'.format(i, clock[1] / 1e6)
|
||||
cmd += ' "CLKOUT{}_PHASE": "{}",\n'.format(i, clock[2])
|
||||
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:
|
||||
cmd += 'print("#### {} ####")\n'.format(name)
|
||||
cmd += 'clksrc_info = design.trace_ref_clock("{}", block_type="PLL")\n'.format(name)
|
||||
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_PHASE", "CLKOUT1_PHASE", "CLKOUT2_PHASE"]\n'
|
||||
cmd += 'prop_map = design.get_property("{}", clock_source_prop, block_type="PLL")\n'.format(name)
|
||||
cmd += 'pprint.pprint(prop_map)\n'
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
|
|||
from litex.build.generic_platform import *
|
||||
from litex.soc.cores.clock.common import *
|
||||
|
||||
from litex.build.efinix import EfinixDbParser
|
||||
|
||||
class Open(Signal): pass
|
||||
|
||||
#TODO: do somthing else
|
||||
|
@ -61,16 +59,15 @@ class TRIONPLL(Module):
|
|||
# If clkin has a pin number, PLL clock input is EXTERNAL
|
||||
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)
|
||||
|
||||
#tpl = "create_clock -name {clk} -period {period} [get_ports {{{clk}}}]"
|
||||
#sdc = self.platform.toolchain.additional_sdc_commands
|
||||
#sdc.append(tpl.format(clk=block['input_clock_name'], period=1/freq))
|
||||
|
||||
parser = EfinixDbParser(self.platform.efinity_path, self.platform.device)
|
||||
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:
|
||||
self.logger.error("Cannot find a pll with {} as input".format(pad_name))
|
||||
quit()
|
||||
|
@ -115,6 +112,10 @@ class TRIONPLL(Module):
|
|||
block = self.platform.toolchain.ifacewriter.get_block(self.pll_name)
|
||||
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):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue