Example #1
0
		def add_cif_polygons(uv_layer, cif_layer):
			print '%s: adding %d boxes' % (uv_layer.name, len(cif_layer.boxes)) 
			for box in cif_layer.boxes:
				'''
				CIF uses lower left coordinate system
				Convert to internal representation, upper left
				
				UL
					Vertical
						B 22 94 787 2735
					Horizontal
						B 116 22 740 2793
				'''
				#print '.',
				if False:
					print 'start'
					print box.xpos
					print box.ypos
					print box.width
					print box.height
				# FIXME: change this into one operation since this now takes non-negligible amount of time
				#uvp = UVPolygon.from_rect(box.xpos, box.ypos, box.width, box.height)
				uvp = UVPolygon.from_rect_ex(box.xpos, box.ypos, box.width, box.height, flip_height = uv_layer.height)
				if False:
					print uvp
					uvp.show()
				#uvp.flip_horizontal(uv_layer.height)
				#print uvp
				#uvp.show()
				uv_layer.add_uvpolygon(uvp)
Example #2
0
	def from_cif_init(self, file_name = "in.cif"):
		self.vias = Layer()
		self.metal = Layer()
		self.polysilicon = Layer()
		self.diffusion = Layer()
		self.labels = Layer()
		self.metal_gnd = None
		self.metal_vcc = None
		self.default_layer_names()
		
		parsed = CIFParser.parse(file_name)
		
		print 'CIF width: %d' % parsed.width
		print 'CIF height: %d' % parsed.height
		
		self.rebuild_layer_lists(False)
		# Make sizes the furthest point found
		for layer in self.layers + [self.labels]:
			#print 'Setting %s to %s' % (layer.name, parsed.width)
			layer.width = parsed.width
			layer.height = parsed.height
		
		def add_cif_polygons(uv_layer, cif_layer):
			print '%s: adding %d boxes' % (uv_layer.name, len(cif_layer.boxes)) 
			for box in cif_layer.boxes:
				'''
				CIF uses lower left coordinate system
				Convert to internal representation, upper left
				
				UL
					Vertical
						B 22 94 787 2735
					Horizontal
						B 116 22 740 2793
				'''
				#print '.',
				if False:
					print 'start'
					print box.xpos
					print box.ypos
					print box.width
					print box.height
				# FIXME: change this into one operation since this now takes non-negligible amount of time
				#uvp = UVPolygon.from_rect(box.xpos, box.ypos, box.width, box.height)
				uvp = UVPolygon.from_rect_ex(box.xpos, box.ypos, box.width, box.height, flip_height = uv_layer.height)
				if False:
					print uvp
					uvp.show()
				#uvp.flip_horizontal(uv_layer.height)
				#print uvp
				#uvp.show()
				uv_layer.add_uvpolygon(uvp)
				#sys.exit(1)
			# uv_layer.show()
			#sys.exit(1)
			
		print 'Width: %d, height: %d' % (parsed.width, parsed.height)
		print 'Parsed labels: %d' % len(parsed.labels)
		for label in parsed.labels:
			# Make it a smallish object
			# Really 1 pix should be fine...but I'm more afraid of corner cases breaking things
			# Get it working first and then debug corner cases if needed
			# Maybe length should be related to text length
			uvpoly = UVPolygon.from_rect_ex(label.x, label.y, 20, 20, flip_height = parsed.height)
			uvpoly.text = label.text
			print uvpoly 
			#uvpoly.show()
			self.labels.add_uvpolygon(uvpoly)
		#self.labels.show()
		#sys.exit(1)
				
		for layer_id in parsed.layers:
			layer = parsed.layers[layer_id]
			bench = Benchmark()
			# NMOS metal
			if layer_id == CIFLayer.NM:
				add_cif_polygons(self.metal, layer)
			# NMOS poly
			elif layer_id == CIFLayer.NP:
				add_cif_polygons(self.polysilicon, layer)
			# NMOS diffusion
			elif layer_id == CIFLayer.ND:
				add_cif_polygons(self.diffusion, layer)
			# NMOS contact
			elif layer_id == CIFLayer.NC:
				add_cif_polygons(self.vias, layer)
			else:
				raise Exception('Unsupported layer type %s' % repr(layer_id))
			print bench
			
		#self.compute_wh()
		self.init()
Example #3
0
    def parse_statement(self, statement, scalar=None):
        '''Must be comment free and stripped of extra spaces.  Return True on end'''
        global box_limit
        global g_limit_polygon

        # Skip blanks
        if statement == '':
            return False
        if False:
            scalar = 1.0
            self.scalar = 1.0

        #print 'Parising %s' % statement

        parts = statement.split()
        key = parts[0].upper()

        print_orig = g_print_result

        if self.cur_subroutine:
            if key == "DF":
                if self.cur_subroutine is None:
                    raise Exception('DF without DS')
                # Note that we correctly drop the old routine if unneeded
                self.subroutines[
                    self.cur_subroutine.number] = self.cur_subroutine
                # Not sure if this is true, but it seems logical anyway
                self.active_layer = None
                self.cur_subroutine = None
                return False
            else:
                self.cur_subroutine.add(statement)
                return False

        ret = False
        if key == "E":
            ret = True
        elif key == "L":
            layer_id = Layer.str2id(parts[1])
            # Hmm can you switch layers?  Probably
            if layer_id in self.layers:
                self.active_layer = self.layers[layer_id]
            else:
                self.active_layer = Layer()
                self.active_layer.id = layer_id
                self.layers[layer_id] = self.active_layer
            if BOX_MAX:
                box_limit = 0
        elif key == "C":
            '''
			Call a subroutine
			
			Syntax:
			C <number>
			'''
            self.subroutines[int(parts[1])].call(self)
            print_orig = False
        elif key == "DS":
            '''
			Define the start of a subroutine
			
			Syntax:
			DS <number> <scale numerator> <scale demon>
			'''
            subroutine = Subroutine()
            subroutine.number = int(parts[1])
            subroutine.scale_numerator = int(parts[2])
            subroutine.scale_denominator = int(parts[3])
            self.cur_subroutine = subroutine
            print_orig = False
        elif key == "B":
            print_orig = False

            if BOX_MAX:
                if box_limit == BOX_MAX:
                    print 'Last accepted box: ' + repr(statement)
                if box_limit > BOX_MAX:
                    return False
                box_limit += 1
            '''
			Syntax:	
			B <length> <width> <xpos> <ypos> [rotation] ;
			'''
            if self.active_layer is None:
                raise Exception('Must be in layer to use box')
            '''
			 B length width xpos ypos [rotation] ;
			a box the center of which is at (xpos, ypos) and is length across in x and width tall in y.
			
			However, I don't like dealing with that so I'm translating
			'''

            width_orig = int(parts[1])
            height_orig = int(parts[2])

            xpos_orig = int(parts[3])
            ypos_orig = int(parts[4])

            width = width_orig * self.scalar
            height = height_orig * self.scalar
            xpos = xpos_orig * self.scalar
            ypos = ypos_orig * self.scalar

            # Lambda design rules FTW
            if not scalar is None:
                xpos *= scalar
                ypos *= scalar
                width *= scalar
                height *= scalar

            xpos_corner = xpos - width / 2.0
            ypos_corner = ypos - height / 2.0

            perform_action = True
            if g_limit_polygon:
                feature_poly = UVPolygon.from_rect_ex(xpos_corner, ypos_corner,
                                                      width, height)
                if not g_limit_polygon.intersects(feature_poly):
                    perform_action = False
            if perform_action:
                # Should truncate to int?  Don't do it unless it becomes a problem

                rotation = None
                if len(parts) >= 6:
                    rotation = int(parts[5])

                if self.corner_coordinates:
                    self.add_box(width, height, xpos_corner, ypos_corner,
                                 rotation)
                else:
                    self.add_box(width, height, xpos, ypos, rotation)

                if g_print_result:
                    rotation_str = ''
                    if not rotation is None:
                        rotation_str = ' %d' % rotation
                    width_i = int(width)
                    height_i = int(height)
                    # Skip invalid geometries
                    if not width_i == 0 and not height_i == 0:
                        print 'B %d %d %d %d%s;' % (
                            width_i, height_i, int(xpos + width / 2.0),
                            int(ypos + height / 2.0), rotation_str)
        elif key == "9":
            '''
			Cell name
			
			Syntax:
			9 <text>
			
			Ignore, unused for now
			'''
            self.cell_name = statement[2:]
        elif key == "94":
            '''
			Label
			
			Syntax:
			94 <label token> <x> <y> [layer]
			'''
            text = parts[1]
            x = int(int(parts[2]) * self.scalar)
            y = int(int(parts[3]) * self.scalar)
            # Lambda design rules FTW
            if not scalar is None:
                x *= scalar
                y *= scalar

            layer_id = None
            if len(parts) >= 5:
                layer_str = parts[4]
                layer_id = layer_id = Layer.str2id(layer_str)
            self.add_label(text, x, y, layer_id)
            if g_print_result:
                print_orig = False
                layer_str = ''
                if not layer_id is None:
                    printed_layer_str = ' %s' % layer_str
                print '94 %s %d %d%s;' % (text, x, y, printed_layer_str)
        else:
            raise Exception("Couldn't parse statement %s" % statement)

        if print_orig:
            print statement + ';'

        return ret
Example #4
0
from pr0ntools.jssim.layer import Layer
from pr0ntools.jssim.options import Options
from pr0ntools.jssim.transistor import *
from pr0ntools.jssim.cif.parser import Parser as CIFParser
from pr0ntools.jssim.cif.parser import Layer as CIFLayer
import sys
from pr0ntools.jssim.layer import UVPolygon, Net, Nets, PolygonRenderer, Point

from pr0ntools.jssim.util import set_debug_width, set_debug_height

if False:
	clip_x_min = 250
	clip_x_max = 360
	clip_y_min = 150
	clip_y_max = 250
	clip_poly = UVPolygon.from_rect_ex(clip_x_min, clip_y_min, clip_x_max - clip_x_min + 1, clip_y_max - clip_y_min + 1)
	clip_poly.color = 'white'
else:
	clip_poly = False

class Generator:
	def __init__(self):
		self.vias = None
		self.metal_gnd = None
		self.metal_vcc = None
		self.metal = None
		self.polysilicon = None
		self.diffusion = None
		self.labels = None
	
	@staticmethod
Example #5
0
	def parse_statement(self, statement, scalar = None):
		'''Must be comment free and stripped of extra spaces.  Return True on end'''
		global box_limit
		global g_limit_polygon

		# Skip blanks
		if statement == '':
			return False
		if False:
			scalar = 1.0
			self.scalar = 1.0

		#print 'Parising %s' % statement
		
		parts = statement.split()
		key = parts[0].upper()
		
		print_orig = g_print_result
		
		if self.cur_subroutine:
			if key == "DF":
				if self.cur_subroutine is None:
					raise Exception('DF without DS')
				# Note that we correctly drop the old routine if unneeded
				self.subroutines[self.cur_subroutine.number] = self.cur_subroutine
				# Not sure if this is true, but it seems logical anyway
				self.active_layer = None
				self.cur_subroutine = None
				return False
			else:			
				self.cur_subroutine.add(statement)
				return False
		
		ret = False
		if key == "E":
			ret = True
		elif key == "L":
			layer_id = Layer.str2id(parts[1])
			# Hmm can you switch layers?  Probably
			if layer_id in self.layers:
				self.active_layer = self.layers[layer_id]
			else:
				self.active_layer = Layer()
				self.active_layer.id = layer_id
			 	self.layers[layer_id] = self.active_layer
		 	if BOX_MAX:
		 		box_limit = 0
		elif key == "C":
			'''
			Call a subroutine
			
			Syntax:
			C <number>
			'''
			self.subroutines[int(parts[1])].call(self)
			print_orig = False
		elif key == "DS":
			'''
			Define the start of a subroutine
			
			Syntax:
			DS <number> <scale numerator> <scale demon>
			'''
			subroutine = Subroutine()
			subroutine.number = int(parts[1])
			subroutine.scale_numerator = int(parts[2])
			subroutine.scale_denominator = int(parts[3])
			self.cur_subroutine = subroutine
			print_orig = False
		elif key == "B":
			print_orig = False
					
			if BOX_MAX:
				if box_limit == BOX_MAX:
					print 'Last accepted box: ' + repr(statement)
				if box_limit > BOX_MAX:
					return False
				box_limit += 1
			
			'''
			Syntax:	
			B <length> <width> <xpos> <ypos> [rotation] ;
			'''
			if self.active_layer is None:
				raise Exception('Must be in layer to use box')
			'''
			 B length width xpos ypos [rotation] ;
			a box the center of which is at (xpos, ypos) and is length across in x and width tall in y.
			
			However, I don't like dealing with that so I'm translating
			'''
			
			width_orig = int(parts[1])
			height_orig = int(parts[2])

			xpos_orig = int(parts[3])
			ypos_orig = int(parts[4])

			
			width = width_orig * self.scalar
			height = height_orig * self.scalar
			xpos = xpos_orig * self.scalar
			ypos = ypos_orig * self.scalar
		
			# Lambda design rules FTW
			if not scalar is None:
				xpos *= scalar
				ypos *= scalar
				width *= scalar
				height *= scalar
			
			xpos_corner = xpos - width / 2.0
			ypos_corner = ypos - height / 2.0
			
			perform_action = True
			if g_limit_polygon:
				feature_poly = UVPolygon.from_rect_ex(xpos_corner, ypos_corner, width, height)
				if not g_limit_polygon.intersects(feature_poly):
					perform_action = False
			if perform_action:			
				# Should truncate to int?  Don't do it unless it becomes a problem
				
				rotation = None
				if len(parts) >= 6:
					rotation = int(parts[5])
				
				if self.corner_coordinates:
					self.add_box(width, height, xpos_corner, ypos_corner, rotation)
				else:
					self.add_box(width, height, xpos, ypos, rotation)
					
				if g_print_result:
					rotation_str = ''
					if not rotation is None:
						rotation_str = ' %d' % rotation
					width_i = int(width)
					height_i = int(height)
					# Skip invalid geometries
					if not width_i == 0 and not height_i == 0:
						print 'B %d %d %d %d%s;' % (width_i, height_i, int(xpos + width / 2.0), int(ypos + height / 2.0), rotation_str)
		elif key == "9":
			'''
			Cell name
			
			Syntax:
			9 <text>
			
			Ignore, unused for now
			'''
			self.cell_name = statement[2:]
		elif key == "94":
			'''
			Label
			
			Syntax:
			94 <label token> <x> <y> [layer]
			'''
			text = parts[1]
			x = int(int(parts[2]) * self.scalar)
			y = int(int(parts[3]) * self.scalar)
			# Lambda design rules FTW
			if not scalar is None:
				x *= scalar
				y *= scalar

			layer_id = None
			if len(parts) >= 5:
				layer_str = parts[4]
				layer_id = layer_id = Layer.str2id(layer_str)
			self.add_label(text, x, y, layer_id)
			if g_print_result:
				print_orig = False
				layer_str = ''
				if not layer_id is None:
					printed_layer_str = ' %s' % layer_str
				print '94 %s %d %d%s;' % (text, x, y, printed_layer_str)
		else:
			raise Exception("Couldn't parse statement %s" % statement)

		if print_orig:
			print statement + ';'

		return ret