From: Staf Verhaegen Date: Sun, 11 Apr 2021 15:38:45 +0000 (+0200) Subject: Wip of P&R of ls180 with C4M FreePDK45. X-Git-Tag: LS180_RC3~145 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c7bbc7f62fe411459cd4bd78f2773ff26e74897d;p=soclayout.git Wip of P&R of ls180 with C4M FreePDK45. build_full.sh can run til after `make vst`, `make lvx` fails. --- diff --git a/experiments9/freepdk_c4m45/Makefile b/experiments9/freepdk_c4m45/Makefile new file mode 100755 index 0000000..d41c688 --- /dev/null +++ b/experiments9/freepdk_c4m45/Makefile @@ -0,0 +1,46 @@ + + LOGICAL_SYNTHESIS = Yosys + PHYSICAL_SYNTHESIS = Coriolis + DESIGN_KIT = FreePDK_C4M45 + YOSYS_FLATTEN = No +# YOSYS_SET_TOP = Yes + CHIP = chip + CORE = ls180 + USE_CLOCKTREE = Yes + USE_DEBUG = No + RM_CHIP = Yes + VST_FLAGS = --vst-uniquify-uppercase + + #NETLISTS = $(shell cat cells.lst) + NETLISTS = ls180 +# YOSYS_FLATTEN = $(shell cat flatten.lst) + + include ./mk/design-flow.mk + +chip_r.vst: ls180.vst + -$(call scl_cols,$(call c2env, cgt -tV --script=doDesign)) + +chip_r.ap: chip_r.vst + +pinmux: + (cd coriolis2 && python ../../../pinmux/src/pinmux_generator.py -v -s ls180 -o ls180) + ln -f -s ../../../pinmux/src/parse.py coriolis2/pinparse.py + ln -f -s coriolis2/ls180 ls180 + +blif: ls180.blif +vst: ls180.vst + +lvx: lvx-chip_r +druc: druc-chip_r +dreal: dreal-chip_r +flatph: flatph-chip_r +view: cgt-chip_r + +layout: chip_r.ap +gds: chip_r.gds +gds_flat: chip_r_flat.gds +cif: chip_r.cif + + +view: cgt-chip_r +sim: asimut-ls180_r diff --git a/experiments9/freepdk_c4m45/build_full.sh b/experiments9/freepdk_c4m45/build_full.sh new file mode 100755 index 0000000..87d19b5 --- /dev/null +++ b/experiments9/freepdk_c4m45/build_full.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +# full core build including QTY 4of 4k SRAMs: please remember to alter +# doDesign.py before running! +# change the settings to the larger chip/corona size +echo "remember to check doDesign core size" + +pdk=`realpath ../../c4m-pdk-freepdk45` +export NDA_TOP=${pdk}/coriolis/techno + +# initialise/update the pinmux & c4m-pdk-freepdk45 submodule +pushd .. +git submodule update --init --remote +popd + +# makes symlinks to alliance +../mksym.sh +touch mk/users.d/user-${USER}.mk +rm -f mk/design-flow.mk +cp design-flow.mk mk/ +lib=${pdk}/views/FreePDK45/FlexLib/liberty/FlexLib_nom.lib +echo "export REAL_MODE = Yes" > mk/dks.d/FreePDK_C4M45.mk +echo "export LIBERTY_FILE = $lib" >> mk/dks.d/FreePDK_C4M45.mk + +# generates the io pads needed for ioring.py +make pinmux + +# clear out +make clean +rm *.vst *.ap + +# copies over a "full" core +cp non_generated/full_core_ls180.il ls180.il + + +# make the vst from ilang +make vst + +# starts the build. +make lvx + diff --git a/experiments9/freepdk_c4m45/coriolis2/__init__.py b/experiments9/freepdk_c4m45/coriolis2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/experiments9/freepdk_c4m45/coriolis2/ioring.py b/experiments9/freepdk_c4m45/coriolis2/ioring.py new file mode 100644 index 0000000..ddebb71 --- /dev/null +++ b/experiments9/freepdk_c4m45/coriolis2/ioring.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +from helpers import l, u, n +import os +import json + +def _byteify(data, ignore_dicts = False): + # if this is a unicode string, return its string representation + if isinstance(data, unicode): + return data.encode('utf-8') + # if this is a list of values, return list of byteified values + if isinstance(data, list): + return [ _byteify(item, ignore_dicts=True) for item in data ] + # if this is a dictionary, return dictionary of byteified keys and values + # but only if we haven't already byteified it + if isinstance(data, dict) and not ignore_dicts: + return dict((_byteify(key, ignore_dicts=True), + _byteify(value, ignore_dicts=True)) + for key, value in data.iteritems()) + # if it's anything else, return it in its original form + return data + +# load JSON-formatted pad info from pinmux +pth = os.path.abspath(__file__) +pth = os.path.split(pth)[0] +print "path", pth +with open("%s/ls180/litex_pinpads.json" % pth) as f: + txt = f.read() +chip = json.loads(txt, object_hook=_byteify) +chip = _byteify(chip, ignore_dicts=True) +print chip + +chip.update({ 'pads.ioPadGauge' : 'pxlib', + # core option (big, time-consuming) + #'core.size' : ( l(28000), l(28000) ), + #'chip.size' : ( l(30200), l(30200) ), + # no-core option (test_issuer but no actual core) + 'core.size' : ( l(13000), l(13000) ), + 'chip.size' : ( l(14400), l(14400) ), + 'pads.useCoreSize': True, + 'chip.clockTree' : True, + }) diff --git a/experiments9/freepdk_c4m45/coriolis2/katana.py b/experiments9/freepdk_c4m45/coriolis2/katana.py new file mode 100644 index 0000000..7a5103f --- /dev/null +++ b/experiments9/freepdk_c4m45/coriolis2/katana.py @@ -0,0 +1,6 @@ +from Hurricane import DebugSession + +#DebugSession.addToTrace( katana.getCell().getNet( 'cu_issue_i' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'cu_wr_rel_o(2)' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'xer_so_ok' ) ) + diff --git a/experiments9/freepdk_c4m45/coriolis2/settings.py b/experiments9/freepdk_c4m45/coriolis2/settings.py new file mode 100644 index 0000000..cc10a52 --- /dev/null +++ b/experiments9/freepdk_c4m45/coriolis2/settings.py @@ -0,0 +1,44 @@ +# -*- Mode:Python -*- + +import os +import socket +import helpers + +NdaDirectory = None +if os.environ.has_key('NDA_TOP'): + NdaDirectory = os.environ['NDA_TOP'] +if not NdaDirectory: + hostname = socket.gethostname() + if hostname.startswith('lepka'): + NdaDirectory = '/dsk/l1/jpc/crypted/soc/techno' + if not os.path.isdir(NdaDirectory): + print '[ERROR] You forgot to mount the NDA encrypted directory, stupid!' + else: + NdaDirectory = '/users/soft/techno/techno' +helpers.setNdaTopDir( NdaDirectory ) + +import Cfg +from CRL import AllianceFramework +from helpers import overlay, l, u, n +from NDA.node45.freepdk45_c4m import techno, FlexLib, LibreSOCIO + +techno.setup() +FlexLib.setup() +LibreSOCIO.setup() + +with overlay.CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg: + cfg.misc.catchCore = False + cfg.misc.minTraceLevel = 12300 + cfg.misc.maxTraceLevel = 12400 + cfg.misc.info = False + cfg.misc.paranoid = False + cfg.misc.bug = False + cfg.misc.logMode = True + cfg.misc.verboseLevel1 = True + cfg.misc.verboseLevel2 = True + cfg.etesian.graphics = 3 + cfg.etesian.spaceMargin = 0.10 + cfg.katana.eventsLimit = 4000000 + af = AllianceFramework.get() + env = af.getEnvironment() + env.setCLOCK( '^sys_clk$|^ck|^jtag_tck$' ) diff --git a/experiments9/freepdk_c4m45/design-flow.mk b/experiments9/freepdk_c4m45/design-flow.mk new file mode 100644 index 0000000..e8b0d12 --- /dev/null +++ b/experiments9/freepdk_c4m45/design-flow.mk @@ -0,0 +1,55 @@ + + include ./mk/os.mk + include ./mk/users.mk + include ./mk/binaries.mk + include ./mk/alliance.mk + +# Some useful functions. + run_if_older = if [ \( ! -e "$(1)" \) -o \( "$(1)" -ot "$(2)" \) ]; then $(3); else echo "\"$(1)\" newer than \"$(2)\" (skip rule)."; fi + +# Select the Design Kit. + ifeq ($(DESIGN_KIT),sxlib) + include ./mk/dks.d/sxlib.mk + else ifeq ($(DESIGN_KIT),nsxlib) + include ./mk/dks.d/nsxlib.mk + else ifeq ($(DESIGN_KIT),nsxlib45) + include ./mk/dks.d/nsxlib45.mk + else ifeq ($(DESIGN_KIT),Hibikino) + include ./mk/dks.d/sxlib-hibikino.mk + else ifeq ($(DESIGN_KIT),FreePDK_45) + include ./mk/dks.d/FreePDK_45.mk + else ifeq ($(DESIGN_KIT),phenitec06) + include ./mk/dks.d/phenitec06.mk + else ifeq ($(DESIGN_KIT),cmos45) + include ./mk/dks.d/nsxlib45.mk + else ifeq ($(DESIGN_KIT),c35b4) + include ./mk/dks.d/c35b4.mk + else ifeq ($(DESIGN_KIT),FlexLib018) + include ./mk/dks.d/FlexLib018.mk + else ifeq ($(DESIGN_KIT),FreePDK_C4M45) + include ./mk/dks.d/FreePDK_C4M45.mk + else + $(error DESIGN_KIT variable has not been set or has an unsupported value) + endif + +# Select the logical synthesis tools. + ifeq ($(LOGICAL_SYNTHESIS),Yosys) + include ./mk/synthesis-yosys.mk + else ifeq ($(LOGICAL_SYNTHESIS),Alliance) + include ./mk/synthesis-alliance.mk + else + include ./mk/synthesis-disabled.mk + endif + +# Select the physical synthesis tools. + ifeq ($(PHYSICAL_SYNTHESIS),Coriolis) + include ./mk/pr-coriolis.mk + else ifeq ($(PHYSICAL_SYNTHESIS),Alliance) + include ./mk/pr-alliance.mk + else ifeq ($(PHYSICAL_SYNTHESIS),Hibikino) + include ./mk/pr-hibikino.mk + else + $(error PHYSICAL_SYNTHESIS variable has not been set or has an unsupported value) + endif + + $(info Using RDS_TECHNO_NAME = "${RDS_TECHNO_NAME}") diff --git a/experiments9/freepdk_c4m45/doDesign.py b/experiments9/freepdk_c4m45/doDesign.py new file mode 100644 index 0000000..dbd4dde --- /dev/null +++ b/experiments9/freepdk_c4m45/doDesign.py @@ -0,0 +1,308 @@ + +from __future__ import print_function + +import os +import re +import json +import sys +import traceback +import collections +import CRL +import helpers +from helpers import trace, l, u, n +from helpers.io import ErrorMessage, WarningMessage +from helpers.overlay import UpdateSession +import plugins +from Hurricane import Breakpoint, DataBase, DbU, Transformation, Point, Box, \ + Cell, Instance +from plugins.alpha.block.matrix import RegisterMatrix +from plugins.alpha.macro.macro import Macro +from plugins.alpha.block.iospecs import IoSpecs +from plugins.alpha.block.block import Block +from plugins.alpha.block.configuration import IoPin, GaugeConf +from plugins.alpha.core2chip.libresocio import CoreToChip +from plugins.alpha.chip.configuration import ChipConf +from plugins.alpha.chip.chip import Chip + + +af = CRL.AllianceFramework.get() +powerCount = 0 + + +def isiterable ( pyobj ): + if isinstance(pyobj,collections.Iterable): return True + return False + + +def doIoPowerCap ( flags ): + global powerCount + side = flags & IoPin.SIDE_MASK + if flags & IoPin.A_BEGIN: + ioPadPower = [ (side , None, 'power_{}'.format(powerCount), 'vdd' ) + , (side , None, 'ground_{}'.format(powerCount), 'vss' ) + , (side , None, 'ioground_{}'.format(powerCount), 'iovss' ) + , (side , None, 'iopower_{}'.format(powerCount), 'iovdd' ) + ] + else: + ioPadPower = [ (side , None, 'iopower_{}'.format(powerCount), 'iovdd' ) + , (side , None, 'ioground_{}'.format(powerCount), 'iovss' ) + , (side , None, 'ground_{}'.format(powerCount), 'vss' ) + , (side , None, 'power_{}'.format(powerCount), 'vdd' ) + ] + powerCount += 1 + return ioPadPower + + +def doIoPinVector ( ioSpec, bits ): + v = [] + if not isiterable(bits): bits = range(bits) + if not bits: + raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.' + , '(bits={})'.format(bits) + ] ) + if len(ioSpec) == 5: + for bit in bits: + v.append(( ioSpec[0] + , ioSpec[1] + , ioSpec[2].format(bit) + , ioSpec[3].format(bit) + , ioSpec[4].format(bit) )) + elif len(ioSpec) == 6: + for bit in bits: + v.append(( ioSpec[0] + , ioSpec[1] + , ioSpec[2].format(bit) + , ioSpec[3].format(bit) + , ioSpec[4].format(bit) + , ioSpec[5].format(bit) )) + elif len(ioSpec) == 7: + for bit in bits: + v.append(( ioSpec[0] + , ioSpec[1] + , ioSpec[2].format(bit) + , ioSpec[3].format(bit) + , ioSpec[4].format(bit) + , ioSpec[5].format(bit) + , ioSpec[6].format(bit) )) + else: + raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec)) + , '(ioSpec={})'.format(ioSpec) + ] ) + return v + + +def rgetInstance ( cell, path ): + """ + Get the instance designated by path (recursively). The path argument can be + either a string of instance names separated by dots or directly a list of + instances names. + """ + if isinstance(path,str): + path = path.split( '.' ) + elif not isinstance(path,list): + raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither a string or a list ({})"' \ + .format(path) ) + instance = cell.getInstance( path[0] ) + if instance is None: + raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \ + .format(path[0],cell.getName()) ) + if len(path) == 1: + return instance + return rgetInstance( instance.getMasterCell(), path[1:] ) + + +def rsetAbutmentBox ( cell, ab ): + for occurrence in cell.getNonTerminalNetlistInstanceOccurrences(): + masterCell = occurrence.getEntity().getMasterCell() + masterCell.setAbutmentBox( ab ) + +def addPllPlaceHolder ( cell ): + pllPlaceHolder = Cell.create( af.getLibrary(0), 'pllplaceholder' ) + pllPlaceHolder.setAbutmentBox( Box( u(0.0), u(0.0), u(200.0), u(200.0) )) + pllPlaceHolder.setTerminalNetlist( True ) + instance = Instance.create( cell, 'pllPlaceholder', pllPlaceHolder ) + return instance + + +def scriptMain (**kw): + """The mandatory function to be called by Coriolis CGT/Unicorn.""" + global af + #helpers.setTraceLevel( 550 ) + #Breakpoint.setStopLevel( 100 ) + rvalue = True + #coreSize = u(37*90.0) + coreSize = u(59*90.0) + chipBorder = u(2*214.0 + 10*13.0) + ioSpecs = IoSpecs() + #pinmuxFile = './non_generated/litex_pinpads.json' + #pinmuxFile = './coriolis2/ls180/litex_pinpads.json' + #ioSpecs.loadFromPinmux( pinmuxFile ) + # I/O pads, East side. + ioPadsSpec = [] + ioPadsSpec += doIoPowerCap( IoPin.EAST|IoPin.A_BEGIN ) + ioPadsSpec += doIoPinVector( (IoPin.EAST , None, 'sdram_a_{}', 'sdram_a({})', 'sdram_a({})'), 13 ) + ioPadsSpec += doIoPinVector( (IoPin.EAST , None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(8,16) ) + ioPadsSpec += [ (IoPin.EAST , None, 'jtag_tms', 'jtag_tms', 'jtag_tms' ) + , (IoPin.EAST , None, 'jtag_tdi', 'jtag_tdi', 'jtag_tdi' ) + , (IoPin.EAST , None, 'jtag_tdo', 'jtag_tdo', 'jtag_tdo' ) + , (IoPin.EAST , None, 'jtag_tck', 'jtag_tck', 'jtag_tck' ) + ] + ioPadsSpec += doIoPinVector( (IoPin.EAST , None, 'nc_{}', 'nc({})', 'nc({})'), range(4) ) + ioPadsSpec += doIoPowerCap( IoPin.EAST|IoPin.A_END ) + # I/O pads, West side. + ioPadsSpec += doIoPowerCap( IoPin.WEST|IoPin.A_BEGIN ) + ioPadsSpec += [ (IoPin.WEST, None, 'pwm_1', 'pwm(1)', 'pwm(1)' ) ] + ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'eint_{}', 'eint({})', 'eint({})'), 3 ) + ioPadsSpec += [ (IoPin.WEST , None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' ) + , (IoPin.WEST , None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' ) + , (IoPin.WEST , None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' ) + , (IoPin.WEST , None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' ) + , (IoPin.WEST , None, 'sdcard_cmd' , 'sdcard_cmd' , 'sdcard_cmd_i', 'sdcard_cmd_oe', 'sdcard_cmd_o' ) + , (IoPin.WEST , None, 'sdcard_clk' , 'sdcard_clk' , 'sdcard_clk' ) + ] + ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'sdcard_data_{}', 'sdcard_data({})', 'sdcard_data_i({})', 'sdcard_data_oe', 'sdcard_data_o({})'), 4 ) + ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'nc_{}', 'nc({})', 'nc({})'), range(4,16) ) + ioPadsSpec += doIoPowerCap( IoPin.WEST|IoPin.A_END ) + # I/O pads, North side. + ioPadsSpec += doIoPowerCap( IoPin.NORTH|IoPin.A_BEGIN ) + ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 ) + ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe', 'sdram_dq_o({})'), range(0,16) ) + ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 ) + ioPadsSpec += [ (IoPin.NORTH, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' ) + , (IoPin.NORTH, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' ) + , (IoPin.NORTH, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' ) + , (IoPin.NORTH, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' ) + , (IoPin.NORTH, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' ) + , (IoPin.NORTH, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' ) + ] + ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(16,18) ) + ioPadsSpec += doIoPowerCap( IoPin.NORTH|IoPin.A_END ) + # I/O pads, South side. + ioPadsSpec += doIoPowerCap( IoPin.SOUTH|IoPin.A_BEGIN ) + ioPadsSpec += [ (IoPin.SOUTH, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i' ) ] + ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(18,22) ) + ioPadsSpec += [ (IoPin.SOUTH, None, 'spisdcard_clk' , 'spisdcard_clk' , 'spisdcard_clk' ) + , (IoPin.SOUTH, None, 'spisdcard_cs_n', 'spisdcard_cs_n', 'spisdcard_cs_n' ) + , (IoPin.SOUTH, None, 'spisdcard_mosi', 'spisdcard_mosi', 'spisdcard_mosi' ) + , (IoPin.SOUTH, None, 'spisdcard_miso', 'spisdcard_miso', 'spisdcard_miso' ) + ] + ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(22,23) ) + ioPadsSpec += [ (IoPin.SOUTH, None, 'uart_tx', 'uart_tx', 'uart_tx' ) + , (IoPin.SOUTH, None, 'uart_rx', 'uart_rx', 'uart_rx' ) + ] + ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,8) ) + ioPadsSpec += [ (IoPin.SOUTH, None, 'sys_clk', 'sys_clk', 'sys_clk' ) + , (IoPin.SOUTH, None, 'sys_rst', 'sys_rst', 'sys_rst' ) + ] + ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'nc_{}', 'nc({})', 'nc({})'), range(23,24) ) + ioPadsSpec += [ (IoPin.SOUTH, None, 'sys_pll_18_o' , 'sys_pll_18_o' , 'sys_pll_18_o' ) ] + ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 ) + ioPadsSpec += [ (IoPin.SOUTH, None, 'sys_pll_lck_o' , 'sys_pll_lck_o' , 'sys_pll_lck_o' ) ] + ioPadsSpec += doIoPowerCap( IoPin.SOUTH|IoPin.A_END ) + try: + cell, editor = plugins.kwParseMain( **kw ) + cell = af.getCell( 'ls180', CRL.Catalog.State.Logical ) + if cell is None: + print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \ + .format('ls180') )) + sys.exit(1) + if editor: editor.setCell( cell ) + #ls180Conf = ChipConf( cell, ioPads=ioSpecs.ioPadsSpec ) + ls180Conf = ChipConf( cell, ioPads=ioPadsSpec ) + ls180Conf.cfg.etesian.bloat = 'nsxlib' + ls180Conf.cfg.etesian.uniformDensity = True + ls180Conf.cfg.etesian.aspectRatio = 1.0 + ls180Conf.cfg.etesian.spaceMargin = 0.05 + ls180Conf.cfg.anabatic.searchHalo = 2 + ls180Conf.cfg.anabatic.globalIterations = 20 + ls180Conf.cfg.anabatic.topRoutingLayer = 'METAL5' + ls180Conf.cfg.katana.hTracksReservedLocal = 6 + ls180Conf.cfg.katana.vTracksReservedLocal = 3 + ls180Conf.cfg.katana.hTracksReservedMin = 3 + ls180Conf.cfg.katana.vTracksReservedMin = 1 + ls180Conf.cfg.block.spareSide = u(7*13) + ls180Conf.cfg.chip.supplyRailWidth = u(35) + ls180Conf.cfg.chip.supplyRailPitch = u(90) + ls180Conf.editor = editor + ls180Conf.useSpares = True + ls180Conf.useClockTree = True + ls180Conf.useHFNS = True + ls180Conf.bColumns = 2 + ls180Conf.bRows = 2 + ls180Conf.chipConf.name = 'chip' + ls180Conf.chipConf.ioPadGauge = 'LibreSOCIO' + ls180Conf.coreSize = (coreSize, coreSize) + ls180Conf.chipSize = (coreSize + chipBorder, coreSize + chipBorder) + + with UpdateSession(): + sliceHeight = ls180Conf.sliceHeight + coreAb = Box( 0, 0, coreSize, coreSize ) + rsetAbutmentBox( cell, coreAb ) + + ls180ToChip = CoreToChip( ls180Conf ) + ls180ToChip.buildChip() + chipBuilder = Chip( ls180Conf ) + chipBuilder.doChipFloorplan() + + with UpdateSession(): + # Thoses ids are dependent on Yosys. They need to be adjusted whenever + # the design changes. + #tiId = 38695 + tiId = 38381 + #sramId = 3695 + sramId = 3300 + tiPath = 'subckt_{}_test_issuer.subckt_1_ti.'.format(tiId) + sramPaths = [ tiPath+'subckt_{}_sram4k_0.subckt_144_SPBlock_512W64B8W'.format(sramId) + , tiPath+'subckt_{}_sram4k_1.subckt_144_SPBlock_512W64B8W'.format(sramId+1) + , tiPath+'subckt_{}_sram4k_2.subckt_144_SPBlock_512W64B8W'.format(sramId+2) + , tiPath+'subckt_{}_sram4k_3.subckt_144_SPBlock_512W64B8W'.format(sramId+3) + ] + sram = DataBase.getDB().getCell( 'SPBlock_512W64B8W' ) + if not sram: + raise ErrorMessage( 1, 'SRAM instance "{}" not found.'.format(sramPaths[i]) ) + sramAb = sram.getAbutmentBox() + coreAb = cell.getAbutmentBox() + sliceHeight = chipBuilder.conf.sliceHeight + originX = coreAb.getXMin() + 2*chipBuilder.conf.sliceStep + for i in range(4): + sram = rgetInstance( cell, sramPaths[i] ) + chipBuilder.placeMacro \ + ( sramPaths[i] + , Transformation( originX + , coreAb.getYMax() - sramAb.getHeight() - 2*sliceHeight + , Transformation.Orientation.ID ) + ) + originX += sramAb.getWidth () + 3*sliceHeight + pll = addPllPlaceHolder( cell ) + pllAb = pll.getAbutmentBox() + pll.setTransformation( Transformation( coreAb.getXMax() - pllAb.getWidth() + , coreAb.getYMax() - pllAb.getHeight() + , Transformation.Orientation.ID ) ) + pll.setPlacementStatus( Instance.PlacementStatus.FIXED ) + #ls180Conf.placeArea = Box( coreAb.getXMin() + # , coreAb.getYMin() + # , coreAb.getXMax() - chipBuilder.conf.sliceStep + # , coreAb.getYMax() - sramAb.getHeight() - 2*sliceHeight + # ) + #memPatterns = [ r'^mem_(?P\d+)__(?P[\d+])$' + # , r'^mem_1_(?P\d+)__(?P[\d+])$' + # , r'^mem_2_(?P\d+)__(?P[\d+])$' + # , r'^mem_3_(?P\d+)__(?P[\d+])$' + # ] + #originX += 2*sliceHeight + #originY = coreAb.getYMax() + #for i in range(len(memPatterns)): + # mem = RegisterMatrix( ls180Conf, cell, memPatterns[i] ) + # originY -= mem.getHeight() + # mem.place( Point(originX,originY) ) + Breakpoint.stop( 99, 'After core placement.' ) + + rvalue = chipBuilder.doPnR() + chipBuilder.save() + CRL.Gds.save( ls180Conf.chip ) + except Exception, e: + helpers.io.catch(e) + rvalue = False + sys.stdout.flush() + sys.stderr.flush() + return rvalue diff --git a/experiments9/freepdk_c4m45/non_generated b/experiments9/freepdk_c4m45/non_generated new file mode 120000 index 0000000..f4c261f --- /dev/null +++ b/experiments9/freepdk_c4m45/non_generated @@ -0,0 +1 @@ +../non_generated \ No newline at end of file