def make_arbiter(name, base_dir, masters, slave=None): """Arbiter module generation. The arbiter module is used to generate all the necessary logic glue to allow multi-masters to got access to a bus or a slave. @param name: arbiter module name @param base_dir: destination directory @param masters: master interfaces signals @param slave: slave interface signals @return: vhdl.Entity instance from Arbiter module. master[0] = InstanceInterface object master[1] = {'signal_name' : 'signal attached'} """ base_name = ("arbiter_%s" % name) filename = path.join(base_dir, ("%s.vhd" % base_name)) try: vhdl_fd = open(filename, "w") except IOError: raise ArbiterError("Can't create %s.vhd file." % base_name) vhdl_fd.write(make_header("Wishbone Round-Robin arbiter module", base_name)) # 1. Building Entity declaration entity = "entity %s is\n" % base_name entity += " port (\n" entity += " -- Global signals\n" entity += " clk : in std_logic;\n" entity += " reset : in std_logic;\n\n" entity += "\n );" entity += "\nend entity;\n" vhdl_fd.write(entity) # 2. Starting Architecture declaration vhdl_fd.write(_VHDL_ARCHITECTURE % (base_name)) # 3. Adding local signals vhdl_fd.write(to_comment(['Signals declaration'])) vhdl_fd.write("begin\n") # 7. Closing module vhdl_fd.write("end architecture;\n") vhdl_fd.close() # 8. Create vhdl.Entity object entity = Entity(StringIO(entity)) instance = Instance(entity, base_name) # 9. Adding signals interconnection # 10. Returning instance return instance, ("%s.vhd" % base_name)
def make_intercon(name, base_dir, master, slaves): """Intercon module generation. The intercon module is used to generate all the necessary logic glue to allow master interface to communicate with each slave. @param name: intercon module name @param base_dir: destination directory @param masters: master interfaces signals @param slaves: slave interfaces signals @return: vhdl.Entity instance from Intercom module. master[0] = InstanceInterface object master[1] = {'signal_name' : 'signal attached'} """ base_name = ("intercon_%s" % name) filename = path.join(base_dir, ("%s.vhd" % base_name)) # Generate master bytes selection signals list _, sel_width = master.wb_signal_width("SEL") byte_width = master.data_width // 8 master_sel = [ mk_sel_bit(master, idx, sel_width, byte_width) for idx in range(byte_width) ] try: vhdl_fd = open(filename, "w") except IOError: raise InterconError("Can't create %s.vhd file." % base_name) vhdl_fd.write(make_header("Wishbone address decoder module", base_name)) # 1. Building Entity declaration entity = "entity %s is\n" % base_name entity += " port (\n" #entity += " -- Global signals\n" #entity += " clk : in std_logic;\n" #entity += " reset : in std_logic;\n\n" entity += " -- Master signals\n" # for signal in master. entity_ports = dict(port_matrix(master, signal, "wbs_master") for _, signal in master.signals.iteritems() ) ports = [" %s : %s" % (key, value[0]) for key, value in entity_ports.iteritems() ] entity += ";\n".join(ports) slaves_max_width = 8 for slave in slaves: entity += ";\n\n -- Slave %s.%s signals\n" % (slave.instance_name, slave.name) if slave.data_width > slaves_max_width: slaves_max_width = slave.data_width # for signal out slave. slave_ports = dict(port_matrix(slave, signal) for _, signal in slave.signals.iteritems() ) entity_ports.update(slave_ports) entity += ";\n".join([" %s : %s" % (key, value[0]) for key, value in slave_ports.iteritems() ]) entity += "\n );" entity += "\nend entity;\n" vhdl_fd.write(entity) # 2. Starting Architecture declaration vhdl_fd.write(_VHDL_ARCHITECTURE % (base_name)) slaves_max_width //= 8 slaves_max_sel = 0 while 2**slaves_max_sel < slaves_max_width: slaves_max_sel += 1 master_sels = [mk_sel_array(master, master_sel, 2**idx) for idx in range(slaves_max_sel+1)] if(len(slaves) > 1): slave_cnx = [InterconRegisterIface(slave, master, "slave_sel(%d)"%idx, master_sels) for idx, slave in enumerate(slaves) ] else: slave_cnx = [InterconRegisterIface(slaves[0], master, "slave_sel", master_sels) ] # 3. Adding local signals vhdl_fd.write(to_comment(['Signals declaration'])) if(len(slaves) > 1): vhdl_fd.write(" signal slave_sel : std_logic_vector(%u downto 0);\n" % (len(slaves) - 1)) else: vhdl_fd.write(" signal slave_sel : std_logic;\n") # 3.1 Adding bytes selection signals for idx, sels in enumerate(master_sels): (_, signals) = sels if len(signals) == 1: vhdl_fd.write(" signal master_sel%u : std_logic;\n" % (8 * (2 ** idx))) else: vhdl_fd.write(" signal master_sel%u : std_logic_vector(%d downto 0);\n" % (8 * (2 ** idx), len(signals) - 1)) vhdl_fd.write("\nbegin\n") # 4. Building address decoders vhdl_fd.write(to_comment(['Byte selection signals'])) for idx, sels in enumerate(master_sels): def _to_signal(sig): if sig == None: return "'1'" else: return sig (_, signals) = sels if len(signals) == 1: vhdl_fd.write(" master_sel%u <= %s;\n" % (8 * (2 ** idx), _to_signal(signals[0]))) else: vhdl = [" master_sel%u(%u) <= %s;\n" % (8 * (2 ** idx), idx2, _to_signal(signals[idx2])) for idx2 in range(len(signals))] vhdl_fd.write("".join(vhdl)) # 4. Building address decoders vhdl_fd.write(to_comment(['Address decoders'])) vhdl = [slave.addr_sel for slave in slave_cnx] vhdl_fd.write(" %s;\n" % ";\n ".join(vhdl)) vhdl = [slave.addr for slave in slave_cnx] vhdl_fd.write(" %s;\n" % ";\n ".join(vhdl)) # 5. Building acknowledge signal vhdl_fd.write(to_comment(['Control signals'])) vhdl = [slave.ack for slave in slave_cnx] vhdl.append("'0'") vhdl_fd.write(" wbs_master_ack_o <= %s;\n" % "\n else ".join(vhdl)) vhdl = [" %s;\n" % ";\n ".join(slave.control) for slave in slave_cnx] vhdl_fd.write("\n".join(vhdl)) # 6. Building datapath vhdl_fd.write(to_comment(['Datapath wrapping'])) vhdl = [slave.byte_sel for slave in slave_cnx if slave.byte_ok] if len(vhdl): vhdl_fd.write(" %s;\n" % ";\n ".join(vhdl)) vhdl = [slave.writedata for slave in slave_cnx if slave.writedata_ok] if len(vhdl): vhdl_fd.write(" %s;\n" % ";\n ".join(vhdl)) if master.has_signal("dat", True): for idx in range(byte_width): vhdl = [slave.readdata(idx) for slave in slave_cnx if slave.readdata_ok(idx) ] vhdl = [elmt for elmt in reduce(list.__add__, vhdl) if elmt != None] name = "wbs_master_dat_o(%d downto %d)" % ((idx*8)+7, idx*8) if len(vhdl) == 0: vhdl_fd.write(" %s <= (others => '0');\n" % name) else: vhdl.append("(others => '0')") sep = "\n%s else " % (" " * (len(name) + 5)) vhdl_fd.write(" %s <= %s;\n" % (name, sep.join(vhdl))) # 7. Closing module vhdl_fd.write("\nend architecture;\n") vhdl_fd.close() # 8. Create vhdl.Entity object entity = Entity(StringIO(entity)) instance = Instance(entity, "CP_" + base_name) # 9. Adding signals interconnection ports = dict((key, value[1]) for key, value in entity_ports.iteritems()) instance.setPorts(ports) # 10. Returning instance return instance, base_name+".vhd"
def make_testbench(project): """Testbench module generation. The testbench module is used to generate all the necessary code to create a instance of System on Chip and to start simulation. @param project: System on Chip project settings """ base_name = ("%s_tb" % project.name) project.entity.name = base_name filename = path.join(project.path, ("%s.vhd" % base_name)) try: vhdl_fd = open(filename, "w") except IOError: raise TestbenchError("Can't create %s.vhd file." % base_name) vhdl_fd.write(make_header("System on Chip testbench skeleton.", base_name)) # 1. Building Entity declaration vhdl_fd.write("entity %s is\nend entity;\n" % base_name) # 2. Starting Architecture declaration vhdl_fd.write(_VHDL_ARCHITECTURE % (base_name)) # 3. Adding project constants vhdl_fd.write(to_comment(['Project constants'])) reset_min = 0 const_def = [] # 3.1 Define constant for each clock frequency for clk in project.soc.clocks.iteritems(): const_def.append(" constant %s_PERIOD : time := 1 sec / %d;" % (clk.name.upper(), clk.frequency)) if clk.frequency < reset_min or reset_min == 0: reset_min = clk.frequency # 3.2 Define reset timing const_def.append(" constant RESET_ON : time := 1 sec / %d;" % (reset_min * 3)) const_def.append(" constant RESET_OFF : time := RESET_ON * 5;") # 3.3 Define constant for each slave interface base address for inst in project.instances.itervalues(): for iface in inst.interfaces.itervalues(): if iface.type == "WBS": const_def.append(" constant %s_%s_BASE_ADDR : integer := %d;" % (inst.name.upper(), iface.name.upper(), iface.offset)) vhdl_fd.write("\n".join(const_def)) vhdl_fd.write("\n") # 4. Adding local signals vhdl_fd.write(to_comment(['Signals declaration'])) vhdl_fd.write(" signal reset : std_logic;\n") vhdl_fd.write("".join([" signal %s : %s := '0';\n" % (name, sig_type) for name, sig_type in project.clock_list.iteritems() ])) vhdl_fd.write("".join([" signal %s : %s;\n" % (name, sig_type) for name, sig_type in project.port_list.iteritems() ])) # 4.1. Connecting signals to Top entity project.entity.setPorts(dict((name, name) for name in project.port_list.iterkeys())) project.entity.setPorts(dict((name, name) for name in project.clock_list.iterkeys())) project.entity.setPorts({"reset":"reset"}) # 5. Adding entity declaration vhdl_fd.write(to_comment(['Components declaration'])) vhdl_fd.write(project.entity.asComponent) vhdl_fd.write("\n\nbegin\n") # 6. Clocks and reset signals generation vhdl_fd.write(" reset <= '0', '1' after RESET_ON, '0' after RESET_OFF;\n") vhdl_fd.write("".join([" %s <= not %s after %s_PERIOD/2;\n" % (name, name, name) for name in project.clock_list.keys() ])) # 7. Adding SoC Top entity vhdl_fd.write(str(project.entity)) # 8. Closing testbench vhdl_fd.write("end architecture;\n") vhdl_fd.close() # 9. Returning file name return ("%s.vhd" % base_name)