Merge pull request #2100 from VOGL-electronic/efinix_io_optimize
efinix: gpio: use constant output option
This commit is contained in:
commit
8041969e00
|
@ -38,6 +38,20 @@ if _have_colorama:
|
||||||
def assert_is_signal_or_clocksignal(obj):
|
def assert_is_signal_or_clocksignal(obj):
|
||||||
assert isinstance(obj, (ClockSignal, Signal)), f"Object {obj} is not a ClockSignal or Signal"
|
assert isinstance(obj, (ClockSignal, Signal)), f"Object {obj} is not a ClockSignal or Signal"
|
||||||
|
|
||||||
|
def const_output_calc(o, io):
|
||||||
|
if o.value == 0:
|
||||||
|
const_output = 0
|
||||||
|
elif len(o) == 1:
|
||||||
|
const_output = 1
|
||||||
|
else:
|
||||||
|
const_output = []
|
||||||
|
for bit in range(len(io)):
|
||||||
|
if o.value & (1 << bit):
|
||||||
|
const_output.append(1)
|
||||||
|
else:
|
||||||
|
const_output.append(0)
|
||||||
|
return const_output
|
||||||
|
|
||||||
# Efinix AsyncResetSynchronizer --------------------------------------------------------------------
|
# Efinix AsyncResetSynchronizer --------------------------------------------------------------------
|
||||||
|
|
||||||
class EfinixAsyncResetSynchronizerImpl(LiteXModule):
|
class EfinixAsyncResetSynchronizerImpl(LiteXModule):
|
||||||
|
@ -142,12 +156,16 @@ class EfinixTristateImpl(LiteXModule):
|
||||||
io_pad = platform.get_pins_location(io)
|
io_pad = platform.get_pins_location(io)
|
||||||
io_prop = platform.get_pin_properties(io[0])
|
io_prop = platform.get_pin_properties(io[0])
|
||||||
io_prop_dict = dict(io_prop)
|
io_prop_dict = dict(io_prop)
|
||||||
io_data_i = platform.add_iface_io(io_name + "_OUT", len(io))
|
if isinstance(o, Constant):
|
||||||
io_data_o = platform.add_iface_io(io_name + "_IN", len(io))
|
const_output = const_output_calc(o, io)
|
||||||
|
else:
|
||||||
|
const_output = "NONE"
|
||||||
|
io_data_i = platform.add_iface_io(io_name + "_OUT", len(io))
|
||||||
|
self.comb += io_data_i.eq(o)
|
||||||
io_data_e = platform.add_iface_io(io_name + "_OE", len(io))
|
io_data_e = platform.add_iface_io(io_name + "_OE", len(io))
|
||||||
self.comb += io_data_i.eq(o)
|
|
||||||
self.comb += io_data_e.eq(oe)
|
self.comb += io_data_e.eq(oe)
|
||||||
if i is not None:
|
if i is not None:
|
||||||
|
io_data_o = platform.add_iface_io(io_name + "_IN", len(io))
|
||||||
self.comb += i.eq(io_data_o)
|
self.comb += i.eq(io_data_o)
|
||||||
block = {
|
block = {
|
||||||
"type" : "GPIO",
|
"type" : "GPIO",
|
||||||
|
@ -156,6 +174,7 @@ class EfinixTristateImpl(LiteXModule):
|
||||||
"location" : io_pad,
|
"location" : io_pad,
|
||||||
"properties" : io_prop,
|
"properties" : io_prop,
|
||||||
"size" : len(io),
|
"size" : len(io),
|
||||||
|
"const_output" : const_output,
|
||||||
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
|
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
|
||||||
}
|
}
|
||||||
platform.toolchain.ifacewriter.blocks.append(block)
|
platform.toolchain.ifacewriter.blocks.append(block)
|
||||||
|
@ -326,10 +345,14 @@ class EfinixSDRTristateImpl(LiteXModule):
|
||||||
io_pad = platform.get_pin_location(io)
|
io_pad = platform.get_pin_location(io)
|
||||||
io_prop = platform.get_pin_properties(io)
|
io_prop = platform.get_pin_properties(io)
|
||||||
io_prop_dict = dict(io_prop)
|
io_prop_dict = dict(io_prop)
|
||||||
io_data_i = platform.add_iface_io(io_name + "_OUT")
|
if isinstance(o, Constant):
|
||||||
|
const_output = const_output_calc(o, io)
|
||||||
|
else:
|
||||||
|
const_output = "NONE"
|
||||||
|
io_data_i = platform.add_iface_io(io_name + "_OUT")
|
||||||
|
self.comb += io_data_i.eq(o)
|
||||||
io_data_o = platform.add_iface_io(io_name + "_IN")
|
io_data_o = platform.add_iface_io(io_name + "_IN")
|
||||||
io_data_e = platform.add_iface_io(io_name + "_OE")
|
io_data_e = platform.add_iface_io(io_name + "_OE")
|
||||||
self.comb += io_data_i.eq(o)
|
|
||||||
self.comb += io_data_e.eq(oe)
|
self.comb += io_data_e.eq(oe)
|
||||||
self.comb += i.eq(io_data_o)
|
self.comb += i.eq(io_data_o)
|
||||||
block = {
|
block = {
|
||||||
|
@ -343,6 +366,7 @@ class EfinixSDRTristateImpl(LiteXModule):
|
||||||
"in_clk_pin" : clk,
|
"in_clk_pin" : clk,
|
||||||
"out_reg" : "REG",
|
"out_reg" : "REG",
|
||||||
"out_clk_pin" : clk,
|
"out_clk_pin" : clk,
|
||||||
|
"const_output" : const_output,
|
||||||
"oe_reg" : "REG",
|
"oe_reg" : "REG",
|
||||||
"in_clk_inv" : 0,
|
"in_clk_inv" : 0,
|
||||||
"out_clk_inv" : 0,
|
"out_clk_inv" : 0,
|
||||||
|
@ -367,8 +391,12 @@ class EfinixSDROutputImpl(LiteXModule):
|
||||||
io_pad = platform.get_pin_location(o)
|
io_pad = platform.get_pin_location(o)
|
||||||
io_prop = platform.get_pin_properties(o)
|
io_prop = platform.get_pin_properties(o)
|
||||||
io_prop_dict = dict(io_prop)
|
io_prop_dict = dict(io_prop)
|
||||||
io_data_i = platform.add_iface_io(io_name)
|
if isinstance(i, Constant):
|
||||||
self.comb += io_data_i.eq(i)
|
const_output = const_output_calc(i, o)
|
||||||
|
else:
|
||||||
|
const_output = "NONE"
|
||||||
|
io_data_i = platform.add_iface_io(io_name)
|
||||||
|
self.comb += io_data_i.eq(i)
|
||||||
block = {
|
block = {
|
||||||
"type" : "GPIO",
|
"type" : "GPIO",
|
||||||
"mode" : "OUTPUT",
|
"mode" : "OUTPUT",
|
||||||
|
@ -378,6 +406,7 @@ class EfinixSDROutputImpl(LiteXModule):
|
||||||
"size" : 1,
|
"size" : 1,
|
||||||
"out_reg" : "REG",
|
"out_reg" : "REG",
|
||||||
"out_clk_pin" : clk,
|
"out_clk_pin" : clk,
|
||||||
|
"const_output" : const_output,
|
||||||
"out_clk_inv" : 0,
|
"out_clk_inv" : 0,
|
||||||
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
|
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,38 +169,9 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
|
||||||
for i, pad in enumerate(block["location"]):
|
for i, pad in enumerate(block["location"]):
|
||||||
cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n'
|
cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n'
|
||||||
|
|
||||||
if "out_reg" in block:
|
|
||||||
cmd += f'design.set_property("{name}","OUT_REG","{block["out_reg"]}")\n'
|
|
||||||
cmd += f'design.set_property("{name}","OUT_CLK_PIN","{block["out_clk_pin"]}")\n'
|
|
||||||
if "out_delay" in block:
|
|
||||||
cmd += f'design.set_property("{name}","OUTDELAY","{block["out_delay"]}")\n'
|
|
||||||
|
|
||||||
if "out_clk_inv" in block:
|
|
||||||
cmd += f'design.set_property("{name}","IS_OUTCLK_INVERTED","{block["out_clk_inv"]}")\n'
|
|
||||||
|
|
||||||
if "in_reg" in block:
|
|
||||||
cmd += f'design.set_property("{name}","IN_REG","{block["in_reg"]}")\n'
|
|
||||||
cmd += f'design.set_property("{name}","IN_CLK_PIN","{block["in_clk_pin"]}")\n'
|
|
||||||
if "in_delay" in block:
|
|
||||||
cmd += f'design.set_property("{name}","INDELAY","{block["in_delay"]}")\n'
|
|
||||||
|
|
||||||
if "in_clk_inv" in block:
|
|
||||||
cmd += f'design.set_property("{name}","IS_INCLK_INVERTED","{block["in_clk_inv"]}")\n'
|
|
||||||
|
|
||||||
if "oe_reg" in block:
|
if "oe_reg" in block:
|
||||||
cmd += f'design.set_property("{name}","OE_REG","{block["oe_reg"]}")\n'
|
cmd += f'design.set_property("{name}","OE_REG","{block["oe_reg"]}")\n'
|
||||||
|
|
||||||
if "drive_strength" in block:
|
|
||||||
cmd += 'design.set_property("{}","DRIVE_STRENGTH","{}")\n'.format(name, block["drive_strength"])
|
|
||||||
if "slewrate" in block:
|
|
||||||
cmd += 'design.set_property("{}","SLEWRATE","{}")\n'.format(name, block["slewrate"])
|
|
||||||
|
|
||||||
if prop:
|
|
||||||
for p, val in prop:
|
|
||||||
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
|
|
||||||
cmd += "\n"
|
|
||||||
return cmd
|
|
||||||
|
|
||||||
if mode == "INPUT":
|
if mode == "INPUT":
|
||||||
if len(block["location"]) == 1:
|
if len(block["location"]) == 1:
|
||||||
cmd += f'design.create_input_gpio("{name}")\n'
|
cmd += f'design.create_input_gpio("{name}")\n'
|
||||||
|
@ -209,6 +180,8 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
|
||||||
cmd += f'design.create_input_gpio("{name}",{block["size"]-1},0)\n'
|
cmd += f'design.create_input_gpio("{name}",{block["size"]-1},0)\n'
|
||||||
for i, pad in enumerate(block["location"]):
|
for i, pad in enumerate(block["location"]):
|
||||||
cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n'
|
cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n'
|
||||||
|
|
||||||
|
if mode == "INPUT" or mode == "INOUT":
|
||||||
if "in_reg" in block:
|
if "in_reg" in block:
|
||||||
in_clk_pin = block["in_clk_pin"]
|
in_clk_pin = block["in_clk_pin"]
|
||||||
if isinstance(in_clk_pin, ClockSignal):
|
if isinstance(in_clk_pin, ClockSignal):
|
||||||
|
@ -225,21 +198,17 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
|
||||||
cmd += f'design.set_property("{name}","INDELAY","{block["in_delay"]}")\n'
|
cmd += f'design.set_property("{name}","INDELAY","{block["in_delay"]}")\n'
|
||||||
if "in_clk_inv" in block:
|
if "in_clk_inv" in block:
|
||||||
cmd += f'design.set_property("{name}","IS_INCLK_INVERTED","{block["in_clk_inv"]}")\n'
|
cmd += f'design.set_property("{name}","IS_INCLK_INVERTED","{block["in_clk_inv"]}")\n'
|
||||||
if prop:
|
|
||||||
for p, val in prop:
|
|
||||||
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
|
|
||||||
cmd += "\n"
|
|
||||||
return cmd
|
|
||||||
|
|
||||||
if mode == "OUTPUT":
|
if mode == "OUTPUT":
|
||||||
if len(block["location"]) == 1:
|
if len(block["location"]) == 1:
|
||||||
cmd += 'design.create_output_gpio("{}")\n'.format(name)
|
cmd += 'design.create_output_gpio("{}")\n'.format(name)
|
||||||
cmd += 'design.assign_pkg_pin("{}","{}")\n'.format(name, block["location"][0])
|
cmd += 'design.assign_pkg_pin("{}","{}")\n'.format(name, block["location"][0])
|
||||||
else:
|
else:
|
||||||
cmd += 'design.create_input_gpio("{}",{},0)\n'.format(name, block["size"]-1)
|
cmd += 'design.create_output_gpio("{}",{},0)\n'.format(name, block["size"]-1)
|
||||||
for i, pad in enumerate(block["location"]):
|
for i, pad in enumerate(block["location"]):
|
||||||
cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad)
|
cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad)
|
||||||
|
|
||||||
|
if mode == "OUTPUT" or mode == "INOUT":
|
||||||
if "out_reg" in block:
|
if "out_reg" in block:
|
||||||
cmd += 'design.set_property("{}","OUT_REG","{}")\n'.format(name, block["out_reg"])
|
cmd += 'design.set_property("{}","OUT_REG","{}")\n'.format(name, block["out_reg"])
|
||||||
cmd += 'design.set_property("{}","OUT_CLK_PIN","{}")\n'.format(name, block["out_clk_pin"])
|
cmd += 'design.set_property("{}","OUT_CLK_PIN","{}")\n'.format(name, block["out_clk_pin"])
|
||||||
|
@ -253,7 +222,14 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True)
|
||||||
cmd += 'design.set_property("{}","DRIVE_STRENGTH","{}")\n'.format(name, block["drive_strength"])
|
cmd += 'design.set_property("{}","DRIVE_STRENGTH","{}")\n'.format(name, block["drive_strength"])
|
||||||
if "slewrate" in block:
|
if "slewrate" in block:
|
||||||
cmd += 'design.set_property("{}","SLEWRATE","{}")\n'.format(name, block["slewrate"])
|
cmd += 'design.set_property("{}","SLEWRATE","{}")\n'.format(name, block["slewrate"])
|
||||||
|
if "const_output" in block:
|
||||||
|
if not isinstance(block["const_output"], list):
|
||||||
|
cmd += f'design.set_property("{name}","CONST_OUTPUT","{block["const_output"]}")\n'
|
||||||
|
else:
|
||||||
|
for i, val in enumerate(block["const_output"]):
|
||||||
|
cmd += f'design.set_property("{name}[{i}]","CONST_OUTPUT","{val}")\n'
|
||||||
|
|
||||||
|
if mode == "INOUT" or mode == "INPUT" or mode == "OUTPUT":
|
||||||
if prop:
|
if prop:
|
||||||
for p, val in prop:
|
for p, val in prop:
|
||||||
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
|
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
|
||||||
|
|
|
@ -120,13 +120,13 @@ class InferedSDRTristate(Module):
|
||||||
|
|
||||||
class SDRTristate(Special):
|
class SDRTristate(Special):
|
||||||
def __init__(self, io, o, oe, i, clk=None):
|
def __init__(self, io, o, oe, i, clk=None):
|
||||||
assert len(i) == len(o) == len(oe)
|
|
||||||
Special.__init__(self)
|
Special.__init__(self)
|
||||||
self.io = wrap(io)
|
self.io = wrap(io)
|
||||||
self.o = wrap(o)
|
self.o = wrap(o)
|
||||||
self.oe = wrap(oe)
|
self.oe = wrap(oe)
|
||||||
self.i = wrap(i)
|
self.i = wrap(i)
|
||||||
self.clk = wrap(clk) if clk is not None else ClockSignal()
|
self.clk = wrap(clk) if clk is not None else ClockSignal()
|
||||||
|
assert len(self.i) == len(self.o) == len(self.oe)
|
||||||
|
|
||||||
def iter_expressions(self):
|
def iter_expressions(self):
|
||||||
yield self, "io" , SPECIAL_INOUT
|
yield self, "io" , SPECIAL_INOUT
|
||||||
|
|
Loading…
Reference in New Issue