Skip to content

Commit

Permalink
Merge pull request #2100 from VOGL-electronic/efinix_io_optimize
Browse files Browse the repository at this point in the history
efinix: gpio: use constant output option
  • Loading branch information
enjoy-digital authored Nov 15, 2024
2 parents 8399c91 + 54973eb commit 8041969
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 44 deletions.
43 changes: 36 additions & 7 deletions litex/build/efinix/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@
def assert_is_signal_or_clocksignal(obj):
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 --------------------------------------------------------------------

class EfinixAsyncResetSynchronizerImpl(LiteXModule):
Expand Down Expand Up @@ -142,12 +156,16 @@ def __init__(self, io, o, oe, i=None):
io_pad = platform.get_pins_location(io)
io_prop = platform.get_pin_properties(io[0])
io_prop_dict = dict(io_prop)
io_data_i = platform.add_iface_io(io_name + "_OUT", len(io))
io_data_o = platform.add_iface_io(io_name + "_IN", len(io))
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", len(io))
self.comb += io_data_i.eq(o)
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)
if i is not None:
io_data_o = platform.add_iface_io(io_name + "_IN", len(io))
self.comb += i.eq(io_data_o)
block = {
"type" : "GPIO",
Expand All @@ -156,6 +174,7 @@ def __init__(self, io, o, oe, i=None):
"location" : io_pad,
"properties" : io_prop,
"size" : len(io),
"const_output" : const_output,
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
}
platform.toolchain.ifacewriter.blocks.append(block)
Expand Down Expand Up @@ -326,10 +345,14 @@ def __init__(self, io, o, oe, i, clk):
io_pad = platform.get_pin_location(io)
io_prop = platform.get_pin_properties(io)
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_e = platform.add_iface_io(io_name + "_OE")
self.comb += io_data_i.eq(o)
self.comb += io_data_e.eq(oe)
self.comb += i.eq(io_data_o)
block = {
Expand All @@ -343,6 +366,7 @@ def __init__(self, io, o, oe, i, clk):
"in_clk_pin" : clk,
"out_reg" : "REG",
"out_clk_pin" : clk,
"const_output" : const_output,
"oe_reg" : "REG",
"in_clk_inv" : 0,
"out_clk_inv" : 0,
Expand All @@ -367,8 +391,12 @@ def __init__(self, i, o, clk):
io_pad = platform.get_pin_location(o)
io_prop = platform.get_pin_properties(o)
io_prop_dict = dict(io_prop)
io_data_i = platform.add_iface_io(io_name)
self.comb += io_data_i.eq(i)
if isinstance(i, Constant):
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 = {
"type" : "GPIO",
"mode" : "OUTPUT",
Expand All @@ -378,6 +406,7 @@ def __init__(self, i, o, clk):
"size" : 1,
"out_reg" : "REG",
"out_clk_pin" : clk,
"const_output" : const_output,
"out_clk_inv" : 0,
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
}
Expand Down
48 changes: 12 additions & 36 deletions litex/build/efinix/ifacewriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,38 +169,9 @@ def generate_gpio(self, block, verbose=True):
for i, pad in enumerate(block["location"]):
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:
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 len(block["location"]) == 1:
cmd += f'design.create_input_gpio("{name}")\n'
Expand All @@ -209,6 +180,8 @@ def generate_gpio(self, block, verbose=True):
cmd += f'design.create_input_gpio("{name}",{block["size"]-1},0)\n'
for i, pad in enumerate(block["location"]):
cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n'

if mode == "INPUT" or mode == "INOUT":
if "in_reg" in block:
in_clk_pin = block["in_clk_pin"]
if isinstance(in_clk_pin, ClockSignal):
Expand All @@ -225,21 +198,17 @@ def generate_gpio(self, block, verbose=True):
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 prop:
for p, val in prop:
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
cmd += "\n"
return cmd

if mode == "OUTPUT":
if len(block["location"]) == 1:
cmd += 'design.create_output_gpio("{}")\n'.format(name)
cmd += 'design.assign_pkg_pin("{}","{}")\n'.format(name, block["location"][0])
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"]):
cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad)

if mode == "OUTPUT" or mode == "INOUT":
if "out_reg" in block:
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"])
Expand All @@ -253,7 +222,14 @@ def generate_gpio(self, block, verbose=True):
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 "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:
for p, val in prop:
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
Expand Down
2 changes: 1 addition & 1 deletion litex/build/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ def __init__(self, io, o, oe, i, clk):

class SDRTristate(Special):
def __init__(self, io, o, oe, i, clk=None):
assert len(i) == len(o) == len(oe)
Special.__init__(self)
self.io = wrap(io)
self.o = wrap(o)
self.oe = wrap(oe)
self.i = wrap(i)
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):
yield self, "io" , SPECIAL_INOUT
Expand Down

0 comments on commit 8041969

Please sign in to comment.