def main(args): iname = os.path.basename(args.infiles[0]) yosys.run.add_define("PB_TYPE") vjson = yosys.run.vlog_to_json(args.infiles, flatten=False, aig=False) yj = YosysJSON(vjson) if args.top is not None: top = args.top else: wm = re.match(r"([A-Za-z0-9_]+)\.sim\.v", iname) if wm: top = wm.group(1).upper() else: print( "ERROR file name not of format %.sim.v ({}), cannot detect top level. Manually specify the top level module using --top" .format(iname)) sys.exit(1) tmod = yj.module(top) pb_type_xml = make_pb_type(yj, tmod) args.outfile.write( ET.tostring(pb_type_xml, pretty_print=True, encoding="utf-8", xml_declaration=True).decode('utf-8')) print("Generated {} from {}".format(args.outfile.name, iname)) args.outfile.close()
vjson = yosys.run.vlog_to_json(args.infiles, flatten=False, aig=False) yj = YosysJSON(vjson) if args.top is not None: top = args.top else: wm = re.match(r"([A-Za-z0-9_]+)\.sim\.v", iname) if wm: top = wm.group(1).upper() else: print( "ERROR file name not of format %.sim.v ({}), cannot detect top level. Manually specify the top level module using --top" .format(iname)) sys.exit(1) tmod = yj.module(top) INVALID_INSTANCE = -1 def is_mod_blackbox(mod): """ Returns true if module is annotated with blackbox (or equivilant). Yosys supports 3 attributes that denote blackbox behavior: "blackbox" - Blackbox with no internal wiring "whitebox" - Blackbox with internal connections and timing. "lib_whitebox" - Like "whitebox" when read with "-lib", otherwise attribute is removed. """
def make_pb_type(yj, mod): """Build the pb_type for a given module. mod is the YosysModule object to generate.""" modes = mod.attr("MODES", None) if modes is not None: modes = modes.split(";") mod_pname = mod_pb_name(mod) pb_xml_attrs = dict() pb_xml_attrs["name"] = mod_pname # If we are a blackbox with no modes, then generate a blif_model is_blackbox = is_mod_blackbox(mod) or not mod.cells has_modes = modes is not None print("is_blackbox", is_blackbox, "has_modes?", has_modes) # Process type and class of module mod_cls = mod.CLASS if mod_cls is not None: if mod_cls == "lut": pb_xml_attrs["blif_model"] = ".names" pb_xml_attrs["class"] = "lut" elif mod_cls == "routing": # TODO: pb_xml_attrs["class"] = "routing" pass elif mod_cls == "mux": # TODO: ? pass elif mod_cls == "flipflop": pb_xml_attrs["blif_model"] = ".latch" pb_xml_attrs["class"] = "flipflop" else: assert False, "unknown class {}".format(mod_cls) elif is_blackbox and not has_modes: pb_xml_attrs["blif_model"] = ".subckt " + mod.attr( "MODEL_NAME", mod.name) # set num_pb to 1, it will be updated if this pb_type # will be included by another one pb_xml_attrs["num_pb"] = "1" pb_type_xml = ET.Element("pb_type", pb_xml_attrs, nsmap={'xi': xmlinc.xi_url}) # Process IOs clocks = yosys.run.list_clocks(args.infiles, mod.name) for name, width, bits, iodir in mod.ports: ioattrs = {"name": name, "num_pins": str(width)} pclass = mod.net_attr(name, "PORT_CLASS") if pclass is not None: ioattrs["port_class"] = pclass if name in clocks: ET.SubElement(pb_type_xml, "clock", ioattrs) elif iodir == "input": ET.SubElement(pb_type_xml, "input", ioattrs) elif iodir == "output": ET.SubElement(pb_type_xml, "output", ioattrs) else: assert False, "bidirectional ports not supported in VPR pb_types" if has_modes: for mode in modes: smode = mode.strip() mode_xml = ET.SubElement(pb_type_xml, "mode", {"name": smode}) # Rerun Yosys with mode parameter mode_yj = YosysJSON( yosys.run.vlog_to_json(args.infiles, flatten=False, aig=False, mode=smode, module_with_mode=mod.name)) mode_mod = mode_yj.module(mod.name) make_pb_content(yj, mode_mod, mode_xml, mod_pname, True) else: make_pb_content(yj, mod, pb_type_xml, mod_pname) return pb_type_xml
def make_pb_type( outfile, yj, mod, mode_processing=False, mode_xml=None, mode_name=None ): """Build the pb_type for a given module. mod is the YosysModule object to generate.""" modes = mod.attr("MODES", None) if modes is not None: modes = modes.split(";") mod_pname = mod.name assert mod_pname == mod_pname.upper( ), "pb_type name should be all uppercase. {}".format(mod_pname) pb_attrs = dict() # If we are a blackbox with no modes, then generate a blif_model is_blackbox = is_mod_blackbox(mod) or not mod.cells has_modes = modes is not None print("is_blackbox", is_blackbox, "has_modes?", has_modes) # Process type and class of module model_name = mod.attr("MODEL_NAME", mod.name) assert model_name == model_name.upper( ), "Model name should be uppercase. {}".format(model_name) mod_cls = mod.CLASS if mod_cls is not None: if mod_cls == "lut": pb_attrs["blif_model"] = ".names" pb_attrs["class"] = "lut" elif mod_cls == "routing": # TODO: pb_attrs["class"] = "routing" pass elif mod_cls == "mux": # TODO: ? pass elif mod_cls == "flipflop": pb_attrs["blif_model"] = ".latch" pb_attrs["class"] = "flipflop" else: assert False, "unknown class {}".format(mod_cls) elif is_blackbox and not has_modes: pb_attrs["blif_model"] = ".subckt " + model_name # set num_pb to 1, it will be updated if this pb_type # will be included by another one if mode_xml is None: pb_type_xml = ET.Element( "pb_type", { "num_pb": "1", "name": mod_pname }, nsmap={'xi': xmlinc.xi_url} ) else: pb_type_xml = ET.SubElement( mode_xml, "pb_type", { "num_pb": "1", "name": mode_name }, nsmap={'xi': xmlinc.xi_url} ) if 'blif_model' in pb_attrs: ET.SubElement(pb_type_xml, "blif_model", {}).text = pb_attrs["blif_model"] if 'class' in pb_attrs: ET.SubElement(pb_type_xml, "pb_class", {}).text = pb_attrs["class"] # Create the pins for this pb_type clocks = yosys.run.list_clocks(args.infiles, mod.name) make_ports(clocks, mod, pb_type_xml, "clocks") make_ports(clocks, mod, pb_type_xml, "inputs") make_ports(clocks, mod, pb_type_xml, "outputs") if modes and not mode_processing: for mode in modes: smode = mode.strip() mode_xml = ET.SubElement(pb_type_xml, "mode", {"name": smode}) # Rerun Yosys with mode parameter mode_yj = YosysJSON( yosys.run.vlog_to_json( args.infiles, flatten=False, aig=False, mode=smode, module_with_mode=mod.name ) ) mode_mod = mode_yj.module(mod.name) make_pb_type(outfile, mode_yj, mode_mod, True, mode_xml, smode) # if mode pb_type contains interconnect tag, add new connctions there ic_xml = mode_xml.find("interconnect") print("ic_xml is", ic_xml, file=sys.stderr) if ic_xml is None: ic_xml = ET.SubElement(mode_xml, "interconnect") for (driver_cell, driver_pin), (sink_cell, sink_pin) in mode_interconnects(mod, smode): make_direct_conn( ic_xml, (driver_cell, driver_pin), (sink_cell, sink_pin), {} ) if not modes or mode_processing: routing = children = [] if not is_blackbox: routing, children = get_children(yj, mod) if routing or children: make_container_pb( outfile, yj, mod, mod_pname, pb_type_xml, routing, children ) else: make_leaf_pb(outfile, yj, mod, mod_pname, pb_type_xml) return pb_type_xml