utils: Adding data-width option to mux generation encapsulating ports into a class Signed-off-by: Jeffrey Elms <elmsfu@freshred.net>
diff --git a/v2x/lib/mux.py b/v2x/lib/mux.py index aa6b21d..fab33a8 100644 --- a/v2x/lib/mux.py +++ b/v2x/lib/mux.py
@@ -59,6 +59,32 @@ return self.value +class ModulePort(object): + def __init__(self, pin_type, name, width, index, data_width=1): + self.name = name + self.pin_type = pin_type + self.width = width + self.index = index + self.data_width = data_width + + def getParameterString(self): + if self.width == 1: + return '\tparameter [0:0] %s = 0;\n' % (self.name) + else: + return '\tparameter %s %s = 0;\n' % (self.index, self.name) + + def getDefinition(self): + if self.width == 1: + if self.data_width is not None and self.data_width > 1: + return '\t%s [%d:0] %s;\n' % (self.pin_type.verilog(), + self.data_width - 1, self.name) + else: + return '\t%s %s;\n' % (self.pin_type.verilog(), self.name) + else: + return '\t%s %s %s;\n' % (self.pin_type.verilog(), self.index, + self.name) + + def pb_type_xml(mux_type, mux_name, pins, subckt=None, num_pb=1, comment=""): """Generate <pb_type> XML for a mux. @@ -122,27 +148,36 @@ if comment is not None: pb_type_xml.append(ET.Comment(comment)) - for pin_type, pin_name, pin_width, pin_index in pins: - #assert pin_index < pin_width, ( - # "Pin index {} >= width {} for pin {} {}".format(pin_index, pin_width, pin_name, pin_type)) - if mux_type == MuxType.ROUTING and pin_type == MuxPinType.SELECT: + for port in pins: + #assert port.index < port.width, ( + # "Pin index {} >= width {} for pin {} {}".format(port.index, port.width, port.name, port.pin_type)) + if mux_type == MuxType.ROUTING and port.pin_type == MuxPinType.SELECT: continue + + assert port.width == 1 or port.data_width == 1, 'Only one of width(%d) or data_width(%d) may > 1 for pin %s' % ( + port.width, port.data_width, port.name) + + if port.width == 1 and port.data_width > 1: + num_pins = port.data_width + else: + num_pins = port.width + ET.SubElement( pb_type_xml, - pin_type.direction(), + port.pin_type.direction(), { - 'name': pin_name, - 'num_pins': str(pin_width) + 'name': port.name, + 'num_pins': str(num_pins) }, ) if mux_type == MuxType.LOGIC: - for ipin_type, ipin_name, ipin_width, ipin_index in pins: - if ipin_type not in (MuxPinType.INPUT, MuxPinType.SELECT): + for inport in pins: + if inport.pin_type not in (MuxPinType.INPUT, MuxPinType.SELECT): continue - for opin_type, opin_name, opin_width, opin_index in pins: - if opin_type not in (MuxPinType.OUTPUT, ): + for outport in pins: + if outport.pin_type not in (MuxPinType.OUTPUT, ): continue ET.SubElement( @@ -150,20 +185,20 @@ 'delay_constant', { 'max': "10e-12", - 'in_port': "%s.%s" % (mux_name, ipin_name), - 'out_port': "%s.%s" % (mux_name, opin_name), + 'in_port': "%s.%s" % (mux_name, inport.name), + 'out_port': "%s.%s" % (mux_name, outport.name), }, ) elif mux_type == MuxType.ROUTING: interconnect = ET.SubElement(pb_type_xml, 'interconnect') inputs = [ - "{}.{}".format(mux_name, n) for t, n, _, _ in pins - if t in (MuxPinType.INPUT, ) + "{}.{}".format(mux_name, port.name) for port in pins + if port.pin_type in (MuxPinType.INPUT, ) ] outputs = [ - "{}.{}".format(mux_name, n) for t, n, _, _ in pins - if t in (MuxPinType.OUTPUT, ) + "{}.{}".format(mux_name, port.name) for port in pins + if port.pin_type in (MuxPinType.OUTPUT, ) ] assert len(outputs) == 1
diff --git a/v2x/mux_gen.py b/v2x/mux_gen.py index 4eddbc8..b37c505 100755 --- a/v2x/mux_gen.py +++ b/v2x/mux_gen.py
@@ -34,6 +34,9 @@ parser.add_argument('--width', type=int, default=8, help="Width of the MUX.") parser.add_argument( + '--data-width', type=int, default=1, help="data width of the MUX.") + +parser.add_argument( '--type', choices=['logic', 'routing'], default='logic', @@ -155,6 +158,10 @@ mux_mk = normpath( os.path.join(mydir, '..', 'common', 'make', 'mux.mk'), to=outdir) + if args.data_width > 1 and not args.split_inputs: + assert False, "data_width(%d) > 1 requires using split_inputs" % ( + args.data_width) + if args.name_inputs: assert_eq(args.name_input, parser.get_default("name_input")) args.name_input = None @@ -242,6 +249,9 @@ if args.name_input != parser.get_default('name_input'): print("MUX_INPUT = {}".format(args.name_input), file=f) + if args.data_width > 1: + print("MUX_DATA_WIDTH = {}".format(args.data_width), file=f) + if args.split_selects: print("MUX_SPLIT_SELECTS = 1", file=f) if args.name_selects != parser.get_default('name_selects'): @@ -280,27 +290,34 @@ for i in args.order: if i == 'i': if args.split_inputs: - port_names.extend((mux_lib.MuxPinType.INPUT, - args.name_inputs[j], 1, '[%i]' % j) - for j in range(args.width)) + port_names.extend( + mux_lib.ModulePort(mux_lib.MuxPinType.INPUT, + args.name_inputs[ + j], 1, '[%i]' % j, args.data_width) + for j in range(args.width)) else: # verilog range bounds are inclusive and convention is [<width-1>:0] - port_names.append((mux_lib.MuxPinType.INPUT, args.name_input, - args.width, '[%i:0]' % (args.width - 1))) + port_names.append( + mux_lib.ModulePort(mux_lib.MuxPinType.INPUT, + args.name_input, args.width, + '[%i:0]' % (args.width - 1))) elif i == 's': if args.split_selects: - port_names.extend((mux_lib.MuxPinType.SELECT, - args.name_selects[j], 1, '[%i]' % j) - for j in range(args.width_bits)) + port_names.extend( + mux_lib.ModulePort(mux_lib.MuxPinType.SELECT, + args.name_selects[j], 1, '[%i]' % j) + for j in range(args.width_bits)) else: + # verilog range bounds are inclusive and convention is [<width-1>:0] assert args.name_select is not None - # verilog array range bounds are inclusive and convention is [<width-1>:0] port_names.append( - (mux_lib.MuxPinType.SELECT, args.name_select, - args.width_bits, '[%i:0]' % (args.width_bits - 1))) + mux_lib.ModulePort(mux_lib.MuxPinType.SELECT, + args.name_select, args.width_bits, + '[%i:0]' % (args.width_bits - 1))) elif i == 'o': - port_names.append((mux_lib.MuxPinType.OUTPUT, args.name_output, 1, - '')) + port_names.append( + mux_lib.ModulePort(mux_lib.MuxPinType.OUTPUT, args.name_output, + 1, '', args.data_width)) # ------------------------------------------------------------------------ # Generate the sim.v Verilog module @@ -311,10 +328,10 @@ sim_pathname = os.path.join(outdir, sim_filename) with open(sim_pathname, "w") as f: module_args = [] - for type, name, _, _ in port_names: - if args.type == 'routing' and type == mux_lib.MuxPinType.SELECT: + for port in port_names: + if args.type == 'routing' and port.pin_type == mux_lib.MuxPinType.SELECT: continue - module_args.append(name) + module_args.append(port.name) mux_prefix = {'logic': '', 'routing': 'r'}[args.type] mux_class = {'logic': 'mux', 'routing': 'routing'}[args.type] @@ -334,60 +351,68 @@ f.write('(* blackbox *) (* CLASS="%s" *)\n' % mux_class) f.write("module %s(%s);\n" % (args.name_mux, ", ".join(module_args))) previous_type = None - for type, name, width, index in port_names: - if previous_type != type: + for port in port_names: + if previous_type != port.pin_type: f.write("\n") - previous_type = type - if args.type == 'routing' and type == mux_lib.MuxPinType.SELECT: - if width == 1: - f.write('\tparameter [0:0] %s = 0;\n' % (name)) - else: - f.write('\tparameter %s %s = 0;\n' % (index, name)) + previous_type = port.pin_type + if args.type == 'routing' and port.pin_type == mux_lib.MuxPinType.SELECT: + f.write(port.getParameterString()) continue - - if width == 1: - f.write('\t%s %s;\n' % (type.verilog(), name)) else: - f.write('\t%s %s %s;\n' % (type.verilog(), index, name)) + f.write(port.getDefinition()) f.write("\n") + if args.data_width > 1: + f.write('\tgenvar\tii;\n') + f.write('\tfor(ii=0; ii<%d; ii++) begin: bitmux\n' % + (args.data_width)) + f.write('\tMUX%s mux (\n' % args.width) for i in range(0, args.width): j = 0 - for type, name, width, index in port_names: - if type != mux_lib.MuxPinType.INPUT: + for port in port_names: + if port.pin_type != mux_lib.MuxPinType.INPUT: continue - if j + width <= i: - j += width + if j + port.width <= i: + j += port.width continue break - if width == 1: - f.write('\t\t.I%i(%s),\n' % (i, name)) + if port.width == 1: + if args.data_width > 1: + f.write('\t\t.I%i(%s[ii]),\n' % (i, port.name)) + else: + f.write('\t\t.I%i(%s),\n' % (i, port.name)) else: - f.write('\t\t.I%i(%s[%i]),\n' % (i, name, i - j)) + f.write('\t\t.I%i(%s[%i]),\n' % (i, port.name, i - j)) for i in range(0, args.width_bits): j = 0 - for type, name, width, index in port_names: - if type != mux_lib.MuxPinType.SELECT: + for port in port_names: + if port.pin_type != mux_lib.MuxPinType.SELECT: continue - if j + width < i: - j += width + if j + port.width < i: + j += port.width continue break - if width == 1: - f.write('\t\t.S%i(%s),\n' % (i, name)) + if port.width == 1: + f.write('\t\t.S%i(%s),\n' % (i, port.name)) else: - f.write('\t\t.S%i(%s[%i]),\n' % (i, name, i - j)) + f.write('\t\t.S%i(%s[%i]),\n' % (i, port.name, i - j)) - for type, name, width, index in port_names: - if type != mux_lib.MuxPinType.OUTPUT: + for port in port_names: + if port.pin_type != mux_lib.MuxPinType.OUTPUT: continue break - assert_eq(width, 1) - f.write('\t\t.O(%s)\n\t);\n' % name) + assert_eq(port.width, 1) + if args.data_width > 1: + f.write('\t\t.O(%s[ii])\n\t);\n' % port.name) + else: + f.write('\t\t.O(%s)\n\t);\n' % port.name) + + if args.data_width > 1: + f.write('end\n') f.write('endmodule\n') @@ -414,17 +439,19 @@ input_ports = ET.SubElement(model_xml, 'input_ports') output_ports = ET.SubElement(model_xml, 'output_ports') - for type, name, width, index in port_names: - if type in (mux_lib.MuxPinType.INPUT, mux_lib.MuxPinType.SELECT): + for port in port_names: + if port.pin_type in (mux_lib.MuxPinType.INPUT, + mux_lib.MuxPinType.SELECT): ET.SubElement( input_ports, 'port', { 'name': - name, + port.name, 'combinational_sink_ports': - ','.join(n for t, n, w, i in port_names - if t in (mux_lib.MuxPinType.OUTPUT, )), + ','.join( + port.name for port in port_names + if port.pin_type in (mux_lib.MuxPinType.OUTPUT, )), }) - elif type in (mux_lib.MuxPinType.OUTPUT, ): + elif port.pin_type in (mux_lib.MuxPinType.OUTPUT, ): ET.SubElement(output_ports, 'port', {'name': args.name_output}) models_str = ET.tostring(models_xml, pretty_print=True).decode('utf-8')