Exemple #1
0
 def add_pin(self, name, pin_type="INOUT"):
     """ Adds a pin to the pins list. Default type is INOUT signal. """
     self.pins.append(name)
     self.pin_type[name]=pin_type
     debug.check(pin_type in self.valid_signal_types,
                 "Invalid signaltype for {0}: {1}".format(name,
                                                          pin_type))
Exemple #2
0
    def add_layout_pin_center_segment(self,
                                      text,
                                      layer,
                                      start,
                                      end,
                                      width=None):
        """ Creates a path like pin with center-line convention """

        debug.check(start.x == end.x or start.y == end.y,
                    "Cannot have a non-manhatten layout pin.")

        if width == None:
            minwidth_layer = drc["minwidth_{}".format(layer)]
        else:
            minwidth_layer = width

        # one of these will be zero
        width = max(start.x, end.x) - min(start.x, end.x)
        height = max(start.y, end.y) - min(start.y, end.y)
        ll_offset = vector(min(start.x, end.x), min(start.y, end.y))

        # Shift it down 1/2 a width in the 0 dimension
        if height == 0:
            ll_offset -= vector(0, 0.5 * minwidth_layer)
        if width == 0:
            ll_offset -= vector(0.5 * minwidth_layer, 0)
        # This makes sure it is long enough, but also it is not 0 width!
        height = max(minwidth_layer, height)
        width = max(minwidth_layer, width)

        return self.add_layout_pin(text, layer, ll_offset, width, height)
Exemple #3
0
def setup_paths():
    """ Set up the non-tech related paths. """
    debug.info(2, "Setting up paths...")

    global OPTS

    try:
        OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
    except:
        debug.error("$OPENRAM_HOME is not properly defined.", 1)
    debug.check(os.path.isdir(OPENRAM_HOME),
                "$OPENRAM_HOME does not exist: {0}".format(OPENRAM_HOME))

    # Add all of the subdirs to the python path
    # These subdirs are modules and don't need
    # to be added: characterizer, verify
    subdirlist = [
        item for item in os.listdir(OPENRAM_HOME)
        if os.path.isdir(os.path.join(OPENRAM_HOME, item))
    ]
    for subdir in subdirlist:
        full_path = "{0}/{1}".format(OPENRAM_HOME, subdir)
        debug.check(
            os.path.isdir(full_path),
            "$OPENRAM_HOME/{0} does not exist: {1}".format(subdir, full_path))
        if "__pycache__" not in full_path:
            sys.path.append("{0}".format(full_path))

    if not OPTS.openram_temp.endswith('/'):
        OPTS.openram_temp += "/"
    debug.info(1, "Temporary files saved in " + OPTS.openram_temp)
    def get_dynamic_delay_chain_size(self, previous_stages, previous_fanout):
        """Determine the size of the delay chain used for the Sense Amp Enable using path delays"""
        from math import ceil
        previous_delay_chain_delay = (
            previous_fanout + 1 + self.parasitic_inv_delay) * previous_stages
        debug.info(
            2, "Previous delay chain produced {} delay units".format(
                previous_delay_chain_delay))

        delay_fanout = 3  # This can be anything >=2
        #The delay chain uses minimum sized inverters. There are (fanout+1)*stages inverters and each
        #inverter adds 1 unit of delay (due to minimum size). This also depends on the pinv value
        required_delay = self.wl_delay * self.wl_timing_tolerance - (
            self.sen_delay - previous_delay_chain_delay)
        debug.check(required_delay > 0,
                    "Cannot size delay chain to have negative delay")
        delay_stages = ceil(required_delay /
                            (delay_fanout + 1 + self.parasitic_inv_delay))
        if delay_stages % 2 == 1:  #force an even number of stages.
            delay_stages += 1
            #Fanout can be varied as well but is a little more complicated but potentially optimal.
        debug.info(
            1,
            "Setting delay chain to {} stages with {} fanout to match {} delay"
            .format(delay_stages, delay_fanout, required_delay))
        return (delay_stages, delay_fanout)
Exemple #5
0
    def __init__(self, sram_config, port, name=""):

        sram_config.set_local_config(self)
        self.port = port
        if self.write_size is not None:
            self.num_wmasks = int(self.word_size / self.write_size)
        else:
            self.num_wmasks = 0

        if self.num_spare_cols is None:
            self.num_spare_cols = 0

        if name == "":
            name = "port_data_{0}".format(self.port)
        design.design.__init__(self, name)
        debug.info(
            2, "create data port of size {0} with {1} words per row".format(
                self.word_size, self.words_per_row))

        self.create_netlist()
        if not OPTS.netlist_only:
            debug.check(
                len(self.all_ports) <= 2,
                "Bank layout cannot handle more than two ports.")
            self.create_layout()
            self.add_boundary()
Exemple #6
0
    def __init__(self, inv1_size=2, inv2_size=4, name=""):

        if name == "":
            name = "dff_buf_{0}".format(dff_buf.unique_id)
            dff_buf.unique_id += 1
        design.design.__init__(self, name)
        debug.info(1, "Creating {}".format(self.name))
        self.add_comment("inv1: {0} inv2: {1}".format(inv1_size, inv2_size))

        # This is specifically for SCMOS where the DFF vdd/gnd rails are more than min width.
        # This causes a DRC in the pinv which assumes min width rails. This ensures the output
        # contact does not violate spacing to the rail in the NMOS.
        debug.check(
            inv1_size >= 2,
            "Inverter must be greater than two for rail spacing DRC rules.")
        debug.check(
            inv2_size >= 2,
            "Inverter must be greater than two for rail spacing DRC rules.")

        self.inv1_size = inv1_size
        self.inv2_size = inv2_size

        self.create_netlist()
        if not OPTS.netlist_only:
            self.create_layout()
Exemple #7
0
def setup_paths():
    """ Set up the non-tech related paths. """
    debug.info(2, "Setting up paths...")

    global OPTS

    try:
        OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
    except:
        debug.error("$OPENRAM_HOME is not properly defined.", 1)
    debug.check(os.path.isdir(OPENRAM_HOME),
                "$OPENRAM_HOME does not exist: {0}".format(OPENRAM_HOME))

    debug.check(
        os.path.isdir(OPENRAM_HOME + "/gdsMill"),
        "$OPENRAM_HOME/gdsMill does not exist: {0}".format(OPENRAM_HOME +
                                                           "/gdsMill"))
    sys.path.append("{0}/gdsMill".format(OPENRAM_HOME))
    debug.check(
        os.path.isdir(OPENRAM_HOME + "/tests"),
        "$OPENRAM_HOME/tests does not exist: {0}".format(OPENRAM_HOME +
                                                         "/tests"))
    sys.path.append("{0}/tests".format(OPENRAM_HOME))
    debug.check(
        os.path.isdir(OPENRAM_HOME + "/characterizer"),
        "$OPENRAM_HOME/characterizer does not exist: {0}".format(
            OPENRAM_HOME + "/characterizer"))
    sys.path.append("{0}/characterizer".format(OPENRAM_HOME))
    debug.check(
        os.path.isdir(OPENRAM_HOME + "/router"),
        "$OPENRAM_HOME/router does not exist: {0}".format(OPENRAM_HOME +
                                                          "/router"))
    sys.path.append("{0}/router".format(OPENRAM_HOME))

    if not OPTS.openram_temp.endswith('/'):
        OPTS.openram_temp += "/"
    debug.info(1, "Temporary files saved in " + OPTS.openram_temp)

    cleanup_paths()

    # make the directory if it doesn't exist
    try:
        os.makedirs(OPTS.openram_temp, 0750)
    except OSError as e:
        if e.errno == 17:  # errno.EEXIST
            os.chmod(OPTS.openram_temp, 0750)

    # Don't delete the output dir, it may have other files!
    # make the directory if it doesn't exist
    try:
        os.makedirs(OPTS.out_path, 0750)
    except OSError as e:
        if e.errno == 17:  # errno.EEXIST
            os.chmod(OPTS.out_path, 0750)

    if OPTS.out_path == "":
        OPTS.out_path = "."
    if not OPTS.out_path.endswith('/'):
        OPTS.out_path += "/"
    debug.info(1, "Output saved in " + OPTS.out_path)
Exemple #8
0
    def gen_pwl(self, sig_name, clk_times, data_values, period, slew, setup):
        """
            Generate a PWL stimulus given a signal name and data values at each period.
            Automatically creates slews and ensures each data occurs a setup before the clock
            edge. The first clk_time should be 0 and is the initial time that corresponds
            to the initial value.
        """
        # the initial value is not a clock time
        str = "Clock and data value lengths don't match. {0} clock values, {1} data values for {2}"
        debug.check(
            len(clk_times) == len(data_values),
            str.format(len(clk_times), len(data_values), sig_name))

        # shift signal times earlier for setup time
        times = np.array(clk_times) - setup * period
        values = np.array(data_values) * self.voltage
        half_slew = 0.5 * slew
        self.sf.write("* (time, data): {}\n".format(
            list(zip(clk_times, data_values))))
        self.sf.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
        for i in range(1, len(times)):
            self.sf.write("{0}n {1}v {2}n {3}v ".format(
                times[i] - half_slew, values[i - 1], times[i] + half_slew,
                values[i]))
        self.sf.write(")\n")
Exemple #9
0
    def __init__(self, gds_name=None, module=None):
        """Use the gds file or the cell for the blockages with the top module topName and
        layers for the layers to route on
        """
        self.gds_name = gds_name
        self.module = module
        debug.check(not (gds_name and module),
                    "Specify only a GDS file or module")

        # If we specified a module instead, write it out to read the gds
        # This isn't efficient, but easy for now
        if module:
            gds_name = OPTS.openram_temp + "temp.gds"
            module.gds_write(gds_name)

        # Load the gds file and read in all the shapes
        self.layout = gdsMill.VlsiLayout(units=tech.GDS["unit"])
        self.reader = gdsMill.Gds2reader(self.layout)
        self.reader.loadFromFile(gds_name)
        self.top_name = self.layout.rootStructureName

        self.pins = {}
        self.blockages = []
        # all the paths we've routed so far (to supplement the blockages)
        self.paths = []

        # The boundary will determine the limits to the size of the routing grid
        self.boundary = self.layout.measureBoundary(self.top_name)
        self.ll = vector(self.boundary[0])
        self.ur = vector(self.boundary[1])
Exemple #10
0
    def add_pin(self, pin_name, is_source=False):
        """ 
        Mark the grids that are in the pin rectangle ranges to have the pin property. 
        pin can be a location or a label.
        """

        found_pin = False
        for pin in self.pins[pin_name]:
            (pin_in_tracks,
             blockage_in_tracks) = self.convert_pin_to_tracks(pin)
            if (len(pin_in_tracks) > 0):
                found_pin = True
            if is_source:
                debug.info(
                    1,
                    "Set source: " + str(pin_name) + " " + str(pin_in_tracks))
                self.rg.add_source(pin_in_tracks)
            else:
                debug.info(
                    1,
                    "Set target: " + str(pin_name) + " " + str(pin_in_tracks))
                self.rg.add_target(pin_in_tracks)
            self.rg.add_blockage(blockage_in_tracks)

        if not found_pin:
            self.write_debug_gds()
        debug.check(found_pin, "Unable to find pin on grid.")
Exemple #11
0
 def get_enable_name(self):
     """Returns name used for enable net"""
     # FIXME: A better programmatic solution to designate pins
     enable_name = self.en_name
     debug.check(enable_name in self.pin_names,
                 "Enable name {} not found in pin list".format(enable_name))
     return enable_name
Exemple #12
0
def import_tech():
    """ Dynamically adds the tech directory to the path and imports it. """
    global OPTS

    debug.info(2,"Importing technology: " + OPTS.tech_name)

    # environment variable should point to the technology dir
    try:
        OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH"))
    except:
        debug.error("$OPENRAM_TECH environment variable is not defined.",1)

    # Add all of the paths
    for tech_path in OPENRAM_TECH.split(":"):
        debug.check(os.path.isdir(tech_path),"$OPENRAM_TECH does not exist: {0}".format(tech_path))
        sys.path.append(tech_path)
        debug.info(1, "Adding technology path: {}".format(tech_path))

    # Import the tech 
    try:
        tech_mod = __import__(OPTS.tech_name)
    except ImportError:
        debug.error("Nonexistent technology_setup_file: {0}.py".format(filename), -1)

    OPTS.openram_tech = os.path.dirname(tech_mod.__file__) + "/"


    # Add the tech directory
    tech_path = OPTS.openram_tech
    sys.path.append(tech_path)
    try:
        import tech
    except ImportError:
        debug.error("Could not load tech module.", -1)
    def DRC_LVS(self, final_verification=False, top_level=False):
        """Checks both DRC and LVS for a module"""
        
        # Final verification option does not allow nets to be connected by label.
        # Unit tests will check themselves.
        if OPTS.is_unit_test:
            return
        if not OPTS.check_lvsdrc:
            return
        # Do not run if disabled in options.
        if (OPTS.inline_lvsdrc or top_level):

            global total_drc_errors
            global total_lvs_errors
            tempspice = "{0}/{1}.sp".format(OPTS.openram_temp,self.name)
            tempgds = "{0}/{1}.gds".format(OPTS.openram_temp,self.name)
            self.sp_write(tempspice)
            self.gds_write(tempgds)

            num_drc_errors = verify.run_drc(self.name, tempgds, final_verification) 
            num_lvs_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification) 
            debug.check(num_drc_errors == 0,"DRC failed for {0} with {1} error(s)".format(self.name,num_drc_errors))
            debug.check(num_lvs_errors == 0,"LVS failed for {0} with {1} errors(s)".format(self.name,num_lvs_errors))
            total_drc_errors += num_drc_errors
            total_lvs_errors += num_lvs_errors

            os.remove(tempspice)
            os.remove(tempgds)
Exemple #14
0
    def add_via_center(self, layers, offset, size=[1,1], mirror="R0", rotate=0, implant_type=None, well_type=None):
        """ Add a three layer via structure by the center coordinate accounting for mirroring and rotation. """
        import contact
        via = contact.contact(layer_stack=layers,
                              dimensions=size,
                              implant_type=implant_type,
                              well_type=well_type)
        height = via.height
        width = via.width
        debug.check(mirror=="R0","Use rotate to rotate vias instead of mirror.")
        
        if rotate==0:
            corrected_offset = offset + vector(-0.5*width,-0.5*height)
        elif rotate==90:
            corrected_offset = offset + vector(0.5*height,-0.5*width)
        elif rotate==180:
            corrected_offset = offset + vector(0.5*width,0.5*height)
        elif rotate==270:
            corrected_offset = offset + vector(-0.5*height,0.5*width)
        else:
            debug.error("Invalid rotation argument.",-1)
            

        #print(rotate,offset,"->",corrected_offset)
        self.add_mod(via)
        inst=self.add_inst(name=via.name, 
                           mod=via, 
                           offset=corrected_offset,
                           mirror=mirror,
                           rotate=rotate)
        # We don't model the logical connectivity of wires/paths
        self.connect_inst([])
        return inst
Exemple #15
0
    def add_read(self, comment, address, port):
        """ Add the control values for a read cycle. """
        debug.check(
            port in self.read_ports,
            "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".
            format(port, self.read_ports))
        debug.info(2, comment)
        self.fn_cycle_comments.append(comment)
        self.append_cycle_comment(port, comment)

        self.cycle_times.append(self.t_current)
        self.t_current += self.period
        self.add_control_one_port(port, "read")
        self.add_address(address, port)

        # If the port is also a readwrite then add
        # the same value as previous cycle
        if port in self.write_ports:
            try:
                self.add_data(self.data_value[port][-1], port)
            except:
                self.add_data("0" * (self.word_size + self.num_spare_cols),
                              port)
            try:
                self.add_wmask(self.wmask_value[port][-1], port)
            except:
                self.add_wmask("0" * self.num_wmasks, port)
            self.add_spare_wen("0" * self.num_spare_cols, port)

        #Add noops to all other ports.
        for unselected_port in self.all_ports:
            if unselected_port != port:
                self.add_noop_one_port(unselected_port)
Exemple #16
0
    def analyze(self, probe_address, probe_data, slews, loads):
        """
        Main function to test the delays of different bits.
        """
        debug.check(
            OPTS.num_rw_ports < 2 and OPTS.num_w_ports < 1
            and OPTS.num_r_ports < 1,
            "Bit testing does not currently support multiport.")
        #Dict to hold all characterization values
        char_sram_data = {}

        self.set_probe(probe_address, probe_data)
        #self.prepare_netlist()

        self.load = max(loads)
        self.slew = max(slews)

        # 1) Find a feasible period and it's corresponding delays using the trimmed array.
        feasible_delays = self.find_feasible_period()

        # 2) Find the delays of several bits
        test_bits = self.get_test_bits()
        bit_delays = self.simulate_for_bit_delays(test_bits)

        for i in range(len(test_bits)):
            debug.info(
                1,
                "Bit tested: addr {0[0]} data_pos {0[1]}\n Values {1}".format(
                    test_bits[i], bit_delays[i]))
Exemple #17
0
    def connect_bitline(self, inst1, inst2, inst1_name, inst2_name):
        """
        Connect two pins of two modules. 
        This assumes that they have sufficient space to create a jog
        in the middle between the two modules (if needed).
        """

        # determine top and bottom automatically.
        # since they don't overlap, we can just check the bottom y coordinate.
        if inst1.by() < inst2.by():
            (bottom_inst, bottom_name) = (inst1, inst1_name)
            (top_inst, top_name) = (inst2, inst2_name)
        else:
            (bottom_inst, bottom_name) = (inst2, inst2_name)
            (top_inst, top_name) = (inst1, inst1_name)

        bottom_pin = bottom_inst.get_pin(bottom_name)
        top_pin = top_inst.get_pin(top_name)
        debug.check(bottom_pin.layer == top_pin.layer,
                    "Pin layers do not match.")

        bottom_loc = bottom_pin.uc()
        top_loc = top_pin.bc()

        yoffset = 0.5 * (top_loc.y + bottom_loc.y)
        self.add_path(top_pin.layer, [
            bottom_loc,
            vector(bottom_loc.x, yoffset),
            vector(top_loc.x, yoffset), top_loc
        ])
Exemple #18
0
 def get_wl_name(self, port=0):
     """Get wl name"""
     if props.bitcell.split_wl:
         return "wl{}".format(port)
     else:
         debug.check(port == 0, "One port for bitcell only.")
         return props.bitcell.cell_6t.pin.wl
Exemple #19
0
def setup_paths():
    """ Set up the non-tech related paths. """
    debug.info(2, "Setting up paths...")

    global OPTS

    try:
        OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
    except:
        debug.error("$OPENRAM_HOME is not properly defined.", 1)
    debug.check(os.path.isdir(OPENRAM_HOME),
                "$OPENRAM_HOME does not exist: {0}".format(OPENRAM_HOME))

    # Add all of the subdirs to the python path
    # These subdirs are modules and don't need to be added: characterizer, verify
    for subdir in ["gdsMill", "tests", "router", "modules", "base", "pgates"]:
        full_path = "{0}/{1}".format(OPENRAM_HOME, subdir)
        debug.check(
            os.path.isdir(full_path),
            "$OPENRAM_HOME/{0} does not exist: {1}".format(subdir, full_path))
        sys.path.append("{0}".format(full_path))

    if not OPTS.openram_temp.endswith('/'):
        OPTS.openram_temp += "/"
    debug.info(1, "Temporary files saved in " + OPTS.openram_temp)

    cleanup_paths()

    # make the directory if it doesn't exist
    try:
        os.makedirs(OPTS.openram_temp, 0o750)
    except OSError as e:
        if e.errno == 17:  # errno.EEXIST
            os.chmod(OPTS.openram_temp, 0o750)
Exemple #20
0
    def __init__(self, sram_config, name=""):

        self.sram_config = sram_config
        sram_config.set_local_config(self)
        if self.write_size:
            self.num_wmasks = int(self.word_size / self.write_size)
        else:
            self.num_wmasks = 0

        if name == "":
            name = "bank_{0}_{1}".format(self.word_size, self.num_words)
        design.design.__init__(self, name)
        debug.info(
            2, "create sram of size {0} with {1} words".format(
                self.word_size, self.num_words))

        # The local control signals are gated when we have bank select logic,
        # so this prefix will be added to all of the input signals to create
        # the internal gated signals.
        if self.num_banks > 1:
            self.prefix = "gated_"
        else:
            self.prefix = ""

        self.create_netlist()
        if not OPTS.netlist_only:
            debug.check(
                len(self.all_ports) <= 2,
                "Bank layout cannot handle more than two ports.")
            self.create_layout()
            self.add_boundary()
Exemple #21
0
    def LVS(self, final_verification=False):
        """Checks LVS for a module"""
        import verify

        # Unit tests will check themselves.
        # Do not run if disabled in options.

        # No layout to check
        if OPTS.netlist_only:
            return
        elif (not OPTS.is_unit_test and OPTS.check_lvsdrc
              and (OPTS.inline_lvsdrc or final_verification)):
            tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.name)
            tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name)
            self.lvs_write(tempspice)
            self.gds_write(tempgds)
            num_errors = verify.run_lvs(self.name,
                                        tempgds,
                                        tempspice,
                                        final_verification=final_verification)
            debug.check(
                num_errors == 0, "LVS failed for {0} with {1} error(s)".format(
                    self.name, num_errors))
            if OPTS.purge_temp:
                os.remove(tempspice)
                os.remove(tempgds)
Exemple #22
0
    def __init__(self, sram_config, port, bit_offsets=None, name=""):

        sram_config.set_local_config(self)
        self.port = port
        if self.write_size is not None:
            self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
        else:
            self.num_wmasks = 0

        if self.num_spare_cols is None:
            self.num_spare_cols = 0

        if not bit_offsets:
            bitcell = factory.create(module_type="bitcell")
            self.bit_offsets = []
            for i in range(self.num_cols + self.num_spare_cols):
                self.bit_offsets.append(i * bitcell.width)
        else:
            self.bit_offsets = bit_offsets

        if name == "":
            name = "port_data_{0}".format(self.port)
        super().__init__(name)
        debug.info(
            2, "create data port of size {0} with {1} words per row".format(
                self.word_size, self.words_per_row))

        self.create_netlist()
        if not OPTS.netlist_only:
            debug.check(
                len(self.all_ports) <= 2,
                "Bank layout cannot handle more than two ports.")
            self.create_layout()
            self.add_boundary()
Exemple #23
0
    def retrieve_pins(self, pin_name):
        """
        Retrieve the pin shapes on metal 3 from the layout.
        """
        debug.info(2, "Retrieving pins for {}.".format(pin_name))
        shape_list = self.layout.getAllPinShapes(str(pin_name))
        pin_set = set()
        for shape in shape_list:
            (layer, boundary) = shape
            # GDSMill boundaries are in (left, bottom, right, top) order
            # so repack and snap to the grid
            ll = vector(boundary[0], boundary[1]).snap_to_grid()
            ur = vector(boundary[2], boundary[3]).snap_to_grid()
            rect = [ll, ur]
            pin = pin_layout(pin_name, rect, layer)
            pin_set.add(pin)

        debug.check(len(pin_set) > 0,
                    "Did not find any pin shapes for {0}.".format(str(pin_name)))

        self.pins[pin_name] = pin_set
        self.all_pins.update(pin_set)

        for pin in self.pins[pin_name]:
            debug.info(3, "Retrieved pin {}".format(str(pin)))
Exemple #24
0
    def __init__(self, name, mod, offset=[0, 0], mirror="R0", rotate=0):
        """Initializes an instance to represent a module"""
        geometry.__init__(self)
        debug.check(
            mirror not in ["R90", "R180", "R270"],
            "Please use rotation and not mirroring during instantiation.")

        self.name = name
        self.mod = mod
        self.gds = mod.gds
        self.rotate = rotate
        self.offset = vector(offset).snap_to_grid()
        self.mirror = mirror
        if OPTS.netlist_only:
            self.width = 0
            self.height = 0
        else:
            if mirror in ["R90", "R270"] or rotate in [90, 270]:
                self.width = round_to_grid(mod.height)
                self.height = round_to_grid(mod.width)
            else:
                self.width = round_to_grid(mod.width)
                self.height = round_to_grid(mod.height)
        self.compute_boundary(offset, mirror, rotate)

        debug.info(4, "creating instance: " + self.name)
Exemple #25
0
    def compute_sizes(self):
        """  Computes the organization of the memory using bitcell size by trying to make it square."""

        debug.check(self.num_banks in [1, 2, 4],
                    "Valid number of banks are 1 , 2 and 4.")

        self.num_words_per_bank = self.num_words / self.num_banks
        self.num_bits_per_bank = self.word_size * self.num_words_per_bank

        # Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
        self.bank_area = self.bitcell.width * self.bitcell.height * self.num_bits_per_bank
        self.bank_side_length = sqrt(self.bank_area)

        # Estimate the words per row given the height of the bitcell and the square side length
        self.tentative_num_cols = int(self.bank_side_length /
                                      self.bitcell.width)
        self.words_per_row = self.estimate_words_per_row(
            self.tentative_num_cols, self.word_size)

        # Estimate the number of rows given the tentative words per row
        self.tentative_num_rows = self.num_bits_per_bank / (
            self.words_per_row * self.word_size)
        self.words_per_row = self.amend_words_per_row(self.tentative_num_rows,
                                                      self.words_per_row)

        # Fix the number of columns and rows
        self.num_cols = self.words_per_row * self.word_size
        self.num_rows = self.num_words_per_bank / self.words_per_row

        # Compute the address and bank sizes
        self.row_addr_size = int(log(self.num_rows, 2))
        self.col_addr_size = int(log(self.words_per_row, 2))
        self.bank_addr_size = self.col_addr_size + self.row_addr_size
        self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
Exemple #26
0
    def compute_sizes(self):
        """  Computes the organization of the memory using bitcell size by trying to make it square."""

        self.bitcell = factory.create(module_type="bitcell")
        
        
        debug.check(self.num_banks in [1,2,4], "Valid number of banks are 1 , 2 and 4.")

        self.num_words_per_bank = self.num_words/self.num_banks
        self.num_bits_per_bank = self.word_size*self.num_words_per_bank
        
        # If this was hard coded, don't dynamically compute it!
        if not self.words_per_row:
            # Compute the area of the bitcells and estimate a square bank (excluding auxiliary circuitry)
            self.bank_area = self.bitcell.width*self.bitcell.height*self.num_bits_per_bank
            self.bank_side_length = sqrt(self.bank_area)

            # Estimate the words per row given the height of the bitcell and the square side length
            self.tentative_num_cols = int(self.bank_side_length/self.bitcell.width)
            self.words_per_row = self.estimate_words_per_row(self.tentative_num_cols, self.word_size)

            # Estimate the number of rows given the tentative words per row
            self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
            self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)

        debug.info(1,"Words per row: {}".format(self.words_per_row))
        self.recompute_sizes()
Exemple #27
0
    def compute_bus_sizes(self):
        """ Compute the independent bus widths shared between two and four bank SRAMs """

        # address size + control signals + one-hot bank select signals
        self.num_vertical_line = self.addr_size + self.control_size + log(
            self.num_banks, 2) + 1
        # data bus size
        self.num_horizontal_line = self.word_size

        self.vertical_bus_width = self.m2_pitch * self.num_vertical_line
        # vertical bus height depends on 2 or 4 banks

        self.data_bus_height = self.m3_pitch * self.num_horizontal_line
        self.data_bus_width = 2 * (self.bank.width + self.bank_to_bus_distance
                                   ) + self.vertical_bus_width

        self.control_bus_height = self.m1_pitch * (self.control_size + 2)
        self.control_bus_width = self.bank.width + self.bank_to_bus_distance + self.vertical_bus_width

        self.supply_bus_height = self.m1_pitch * 2  # 2 for vdd/gnd placed with control bus
        self.supply_bus_width = self.data_bus_width

        # Sanity check to ensure we can fit the control logic above a single bank (0.9 is a hack really)
        debug.check(
            self.bank.width + self.vertical_bus_width >
            0.9 * self.control_logic.width,
            "Bank is too small compared to control logic.")
Exemple #28
0
    def __init__(self, name, size=1, height=None, add_wells=True):
        """ Creates a cell for a simple 3 input nand """

        debug.info(2,
                   "creating pnand4 structure {0} with size of {1}".format(name,
                                                                           size))
        self.add_comment("size: {}".format(size))

        # We have trouble pitch matching a 3x sizes to the bitcell...
        # If we relax this, we could size this better.
        self.size = size
        self.nmos_size = 2 * size
        self.pmos_size = parameter["beta"] * size
        self.nmos_width = self.nmos_size * drc("minwidth_tx")
        self.pmos_width = self.pmos_size * drc("minwidth_tx")

        # FIXME: Allow these to be sized
        debug.check(size == 1,
                    "Size 1 pnand4 is only supported now.")
        self.tx_mults = 1

        if OPTS.tech_name == "sky130":
            self.nmos_width = self.nearest_bin("nmos", self.nmos_width)
            self.pmos_width = self.nearest_bin("pmos", self.pmos_width)

        # Creates the netlist and layout
        super().__init__(name, height, add_wells)
Exemple #29
0
def import_tech():
    global OPTS

    debug.info(2,"Importing technology: " + OPTS.tech_name)

    # Set the tech to the config file we read in instead of the command line value.
    OPTS.tech_name = OPTS.tech_name
    
    
        # environment variable should point to the technology dir
    try:
        OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH"))
    except:
        debug.error("$OPENRAM_TECH is not properly defined.",1)
    debug.check(os.path.isdir(OPENRAM_TECH),"$OPENRAM_TECH does not exist: {0}".format(OPENRAM_TECH))
    
    OPTS.openram_tech = OPENRAM_TECH + "/" + OPTS.tech_name
    if not OPTS.openram_tech.endswith('/'):
        OPTS.openram_tech += "/"
    debug.info(1, "Technology path is " + OPTS.openram_tech)

    try:
        filename = "setup_openram_{0}".format(OPTS.tech_name)
        # we assume that the setup scripts (and tech dirs) are located at the
        # same level as the compielr itself, probably not a good idea though.
        path = "{0}/setup_scripts".format(os.environ.get("OPENRAM_TECH"))
        debug.check(os.path.isdir(path),"OPENRAM_TECH does not exist: {0}".format(path))    
        sys.path.append(os.path.abspath(path))
        __import__(filename)
    except ImportError:
        debug.error("Nonexistent technology_setup_file: {0}.py".format(filename))
        sys.exit(1)
Exemple #30
0
    def add_read_one_port(self, comment, address, port):
        """ Add the control values for a read cycle. Does not increment the period. """
        debug.check(
            port in self.read_ports,
            "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".
            format(port, self.read_ports))
        debug.info(2, comment)
        self.fn_cycle_comments.append(comment)

        self.add_control_one_port(port, "read")
        self.add_address(address, port)

        # If the port is also a readwrite then add
        # the same value as previous cycle
        if port in self.write_ports:
            try:
                self.add_data(self.data_value[port][-1], port)
            except:
                self.add_data("0" * (self.word_size + self.num_spare_cols),
                              port)
            try:
                self.add_wmask(self.wmask_value[port][-1], port)
            except:
                self.add_wmask("0" * self.num_wmasks, port)
            self.add_spare_wen("0" * self.num_spare_cols, port)
Exemple #31
0
def disassemble(buf, virt, sections, binary):
    '''
    Disassemble a block of x64 code.
    '''

    virts = [(sections[sect]['virt'], sections[sect]['length']) for sect in sections if sections[sect]['virt']]
    objmin = min(virt[0] for virt in virts)
    objmax = max(virt[0]+virt[1] for virt in virts)
    objbounds = (objmin, objmax)

    FORMAT="INTEL"
    entries = [virt]

    result = {}
    while entries:
        addr = entries.pop()
        off = addr-virt
        while off < len(buf):
            p = Opcode(buf[off:], mode=64)
            pre = p.getPrefix()
            length = p.getSize()
            try:
                ins, r, w = p.getOpcode(FORMAT)
            except ValueError:
                break
            ins = repr_ins(ins, r, w, objbounds, sections, binary)

            if debug.check('asm_rw'):
                print(ins, r, w)

            debug_dis = {
                'prefix': pre,
                'binary': buf[off:off+length]
            }
            result[addr] = {'ins': ins, 'loc': addr, 'length': length, 'debug': debug_dis, 'display': True}
            if ins['op'] == 'return':
                break
#            if ins['op'] == 'call':
#                j_addr = addr+length+ins['dest']['repr']
#                if j_addr not in result:
#                    entries.append(j_addr)
            if ins['op'] == 'jump':
                j_addr = addr+length+ins['dest']['repr']
                if j_addr not in result:
                    entries.append(j_addr)
                result[addr]['display'] = False
                if ins['cond'] == 'true':
                    break
            off += length
            addr += length
    
    return [result[key] for key in sorted(result.keys())]
Exemple #32
0
Fichier : c.py Projet : czxxjtu/ocd
def output_line(line, indent):
    '''
    Output a line of code. A line contains an instruction and
     some metainformation about that instruction (its location,
     etc.)

    The pseudo-EBNF of lines is as follows:

     line = location, debug, instruction
     instruction = op, argument*
     argument = value, repr | instruction
    '''
    def output_ins(ins):
        '''
        Decompile an instruction. Instructions are trees, see
         the EBNF for output_line.
        '''
        repr = {}
        prec = {}
        for k, arg in ins.items():
            if k not in ('src', 'dest'):
                continue

            if 'op' in ins[k]:
                lhs, rhs, prec[k] = output_ins(ins[k])
                repr[k] = rhs
            else:
                repr[k] = ins[k]['repr']
                prec[k] = 20

            if type(repr[k]) == int:
                repr[k] = repr_int(repr[k])

        if ins['op'] == 'apply':
            lhs = ''
            args = []
            for arg in ins['args']:
                if 'op' in arg:
                    lhs, rhs, inner_prec = output_ins(arg)
                    args.append(rhs)
                else:
                    args.append(arg['repr'])
            rhs = '{fun}({args})'.format(fun=ins['function'], args=', '.join(args))
            outer_prec = 20

        else:
            try:
                lhs, rhs, outer_prec = output_op(ins['op'])
            except KeyError:
                lhs, rhs = '', '/* Unsupported immediate instruction: {ins[op]} */'.format(ins=ins)
                outer_prec = 20

        for k in dict(repr):
            if outer_prec > prec[k]:
                repr[k] = '(' + repr[k] + ')'

        return lhs.format(i=repr), rhs.format(i=repr), outer_prec

    lhs, rhs, prec = output_ins(line['ins'])
    line_repr = indent.out() + lhs + rhs
    if lhs+rhs != '':
        line_repr += ';'

    if not line['display']:
        line_repr = ''

    if debug.check('misc'):
        from binascii import hexlify
        line_repr += '\n{indent}{blue}/* {line} */{black}'.format(indent=indent.out(), line=line, blue='\033[94m', black='\033[0m')

    return line_repr