def test_time_est_unchanged(self): a = pyrtl.Const(2, 8) b = pyrtl.Const(85, 8) zero = pyrtl.Const(0, 1) reg = pyrtl.Register(8) mem = pyrtl.MemBlock(8, 8) out = pyrtl.Output(8) nota, aLSB, athenb, aORb, aANDb, aNANDb, \ aXORb, aequalsb, altb, agtb, aselectb, \ aplusb, bminusa, atimesb, memread = [pyrtl.Output() for i in range(15)] out <<= zero nota <<= ~a aLSB <<= a[0] athenb <<= pyrtl.concat(a, b) aORb <<= a | b aANDb <<= a & b aNANDb <<= a.nand(b) aXORb <<= a ^ b aequalsb <<= a == b altb <<= a < b agtb <<= a > b aselectb <<= pyrtl.select(zero, a, b) reg.next <<= a aplusb <<= a + b bminusa <<= a - b atimesb <<= a * b memread <<= mem[0] mem[1] <<= a timing = pyrtl.TimingAnalysis() self.assertEqual(timing.max_freq(), 610.2770657878676) self.assertEqual(timing.max_length(), 1255.6000000000001)
def test_output_to_graphviz_with_custom_namer_does_not_throw_error(self): from .test_importexport import full_adder_blif with io.StringIO() as vfile: pyrtl.input_from_blif(full_adder_blif) timing = pyrtl.TimingAnalysis() node_fan_in = {net: len(net.args) for net in pyrtl.working_block()} graph_namer = pyrtl.graphviz_detailed_namer( extra_node_info=node_fan_in, extra_edge_info=timing.timing_map) pyrtl.output_to_graphviz(vfile, namer=graph_namer)
def everything_t_procedure(self, timing_val=None, opt_timing_val=None): # if there is a nondefault timing val supplied, then it will check # to make sure that the timing matches # this is a subprocess to do the synth and timing block = pyrtl.working_block() timing = pyrtl.TimingAnalysis(block) timing_max_length = timing.max_length() if timing_val is not None: self.assertEqual(timing_max_length, timing_val) critical_path = timing.critical_path(print_cp=False) pyrtl.synthesize() pyrtl.optimize() block = pyrtl.working_block() timing = pyrtl.TimingAnalysis(block) timing_max_length = timing.max_length() if opt_timing_val is not None: self.assertEqual(timing_max_length, opt_timing_val) critical_path = timing.critical_path(print_cp=False) pyrtl.and_inverter_synth() pyrtl.optimize() block = pyrtl.working_block() timing = pyrtl.TimingAnalysis(block) timing_max_length = timing.max_length() critical_path = timing.critical_path(print_cp=False) block = pyrtl.working_block() self.num_net_of_type('|', 0, block) self.num_net_of_type('^', 0, block) pyrtl.nand_synth() pyrtl.optimize() block = pyrtl.working_block() timing = pyrtl.TimingAnalysis(block) timing_max_length = timing.max_length() critical_path = timing.critical_path(print_cp=False) block.sanity_check() self.num_net_of_type('|', 0, block) self.num_net_of_type('^', 0, block) self.num_net_of_type('&', 0, block)
def test_timing_error(self): inwire, inwire2 = pyrtl.Input(bitwidth=1), pyrtl.Input(bitwidth=1) tempwire, tempwire2 = pyrtl.WireVector(1), pyrtl.WireVector(1) outwire = pyrtl.Output() tempwire <<= ~(inwire & tempwire2) tempwire2 <<= ~(inwire2 & tempwire) outwire <<= tempwire output = six.StringIO() sys.stdout = output with self.assertRaises(pyrtl.PyrtlError): pyrtl.synthesize() pyrtl.optimize() block = pyrtl.working_block() _timing = pyrtl.TimingAnalysis(block) sys.stdout = sys.__stdout__ self.assertTrue(output.getvalue().startswith("Loop found:"))
def test_output_to_graphviz_correct_detailed_output(self): pyrtl.wire._reset_wire_indexers() a = pyrtl.Input(2, 'a') b = a * 8 c = b[2:] d = pyrtl.Output(10, 'd') d <<= c analysis = pyrtl.TimingAnalysis() _, dst_map = pyrtl.working_block().net_connections() def get_fanout(n): if isinstance(n, pyrtl.LogicNet): if n.op == '@': return 0 w = n.dests[0] else: w = n if isinstance(w, pyrtl.Output): return 0 else: return len(dst_map[w]) node_fanout = { n: "Fanout: %d" % get_fanout(n) for n in pyrtl.working_block().logic } wire_delay = { w: "Delay: %.2f" % analysis.timing_map[w] for w in pyrtl.working_block().wirevector_set } with io.StringIO() as vfile: pyrtl.output_to_graphviz(file=vfile, namer=pyrtl.graphviz_detailed_namer( node_fanout, wire_delay), maintain_arg_order=True) self.assertEqual(vfile.getvalue(), graphviz_string_detailed)
# Timing and area usage are key considerations of any hardware block that one # makes. PyRTL provides functions to do these operations. # Creating a sample hardware block pyrtl.reset_working_block() const_wire = pyrtl.Const(6, bitwidth=4) in_wire2 = pyrtl.Input(bitwidth=4, name="input2") out_wire = pyrtl.Output(bitwidth=5, name="output") out_wire <<= const_wire + in_wire2 # Now we will do the timing analysis as well as print out the critical path # Generating timing analysis information print("Pre Synthesis:") timing = pyrtl.TimingAnalysis() timing.print_max_length() # We are also able to print out the critical paths as well as get them # back as an array. critical_path_info = timing.critical_path() # --- Part 2: Area Analysis -------------------------------------------------- # PyRTL also provides estimates for the area that would be used up if the # circuit was printed as an ASIC. logic_area, mem_area = pyrtl.area_estimation(tech_in_nm=65) est_area = logic_area + mem_area print("Estimated Area of block", est_area, "sq mm") print()