Updated configuration suited for experiment9/tsmc_c018.
[soclayout.git] / experiments9 / tsmc_c018 / doDesign.py
1
2 from __future__ import print_function
3
4 import os
5 import re
6 import json
7 import sys
8 import traceback
9 import collections
10 import CRL
11 import helpers
12 from helpers import trace, l, u, n
13 from helpers.io import ErrorMessage, WarningMessage
14 from helpers.overlay import UpdateSession
15 import plugins
16 from Hurricane import Breakpoint, DataBase, DbU, Transformation, Point, Box, \
17 Cell, Instance
18 from plugins.alpha.block.matrix import RegisterMatrix
19 from plugins.alpha.macro.macro import Macro
20 from plugins.alpha.block.iospecs import IoSpecs
21 from plugins.alpha.block.block import Block
22 from plugins.alpha.block.configuration import IoPin, GaugeConf
23 from plugins.alpha.core2chip.libresocio import CoreToChip
24 from plugins.alpha.chip.configuration import ChipConf
25 from plugins.alpha.chip.chip import Chip
26 #from plugins.alpha.utils import rgetInstanceMatching
27
28
29 af = CRL.AllianceFramework.get()
30 powerCount = 0
31 placeHolderCount = 0
32
33
34 def onGrid ( v ):
35 twoGrid = DbU.fromGrid( 2 )
36 modulo = v % twoGrid
37 if modulo:
38 v += twoGrid - modulo
39 return v
40
41
42 def isiterable ( pyobj ):
43 if isinstance(pyobj,collections.Iterable): return True
44 return False
45
46
47 def doIoPowerCap ( flags ):
48 global powerCount
49 side = flags & IoPin.SIDE_MASK
50 if flags & IoPin.A_BEGIN:
51 ioPadPower = [ (side , None, 'power_{}'.format(powerCount), 'vdd' )
52 , (side , None, 'ground_{}'.format(powerCount), 'vss' )
53 , (side , None, 'ioground_{}'.format(powerCount), 'iovss' )
54 , (side , None, 'iopower_{}'.format(powerCount), 'iovdd' )
55 ]
56 else:
57 ioPadPower = [ (side , None, 'iopower_{}'.format(powerCount), 'iovdd' )
58 , (side , None, 'ioground_{}'.format(powerCount), 'iovss' )
59 , (side , None, 'ground_{}'.format(powerCount), 'vss' )
60 , (side , None, 'power_{}'.format(powerCount), 'vdd' )
61 ]
62 powerCount += 1
63 return ioPadPower
64
65
66 def doIoPinVector ( ioSpec, bits ):
67 v = []
68 if not isiterable(bits): bits = range(bits)
69 if not bits:
70 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
71 , '(bits={})'.format(bits)
72 ] )
73 if len(ioSpec) == 5:
74 for bit in bits:
75 v.append(( ioSpec[0]
76 , ioSpec[1]
77 , ioSpec[2].format(bit)
78 , ioSpec[3].format(bit)
79 , ioSpec[4].format(bit) ))
80 elif len(ioSpec) == 6:
81 for bit in bits:
82 v.append(( ioSpec[0]
83 , ioSpec[1]
84 , ioSpec[2].format(bit)
85 , ioSpec[3].format(bit)
86 , ioSpec[4].format(bit)
87 , ioSpec[5].format(bit) ))
88 elif len(ioSpec) == 7:
89 for bit in bits:
90 v.append(( ioSpec[0]
91 , ioSpec[1]
92 , ioSpec[2].format(bit)
93 , ioSpec[3].format(bit)
94 , ioSpec[4].format(bit)
95 , ioSpec[5].format(bit)
96 , ioSpec[6].format(bit) ))
97 else:
98 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec))
99 , '(ioSpec={})'.format(ioSpec)
100 ] )
101 return v
102
103
104 def rgetInstance ( cell, path ):
105 """
106 Get the instance designated by path (recursively). The path argument can be
107 either a string of instance names separated by dots or directly a list of
108 instances names.
109 """
110 if isinstance(path,str):
111 path = path.split( '.' )
112 elif not isinstance(path,list):
113 raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither a string or a list ({})"' \
114 .format(path) )
115 instance = cell.getInstance( path[0] )
116 if instance is None:
117 raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \
118 .format(path[0],cell.getName()) )
119 if len(path) == 1:
120 return instance
121 return rgetInstance( instance.getMasterCell(), path[1:] )
122
123
124 def rsetAbutmentBox ( cell, ab ):
125 for occurrence in cell.getNonTerminalNetlistInstanceOccurrences():
126 masterCell = occurrence.getEntity().getMasterCell()
127 masterCell.setAbutmentBox( ab )
128
129
130 def scriptMain (**kw):
131 """The mandatory function to be called by Coriolis CGT/Unicorn."""
132 global af
133 #helpers.setTraceLevel( 550 )
134 #Breakpoint.setStopLevel( 99 )
135 rvalue = True
136 coreSizeX = u(51*90.0)
137 coreSizeY = u(56*90.0)
138 chipBorder = u(2*214.0 + 8*13.0)
139 ioSpecs = IoSpecs()
140 #pinmuxFile = './non_generated/litex_pinpads.json'
141 #pinmuxFile = './coriolis2/ls180/litex_pinpads.json'
142 #ioSpecs.loadFromPinmux( pinmuxFile )
143 # I/O pads, East side.
144 ioPadsSpec = []
145 ioPadsSpec += doIoPowerCap( IoPin.EAST|IoPin.A_BEGIN )
146 ioPadsSpec += doIoPinVector( (IoPin.EAST, None, 'sdram_a_{}' , 'sdram_a({})' , 'sdram_a({})'), 13 )
147 ioPadsSpec += doIoPinVector( (IoPin.EAST, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 )
148 ioPadsSpec += doIoPinVector( (IoPin.EAST, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe({})', 'sdram_dq_o({})'), range(0,16) )
149 ioPadsSpec += doIoPinVector( (IoPin.EAST, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
150 ioPadsSpec += doIoPowerCap( IoPin.EAST|IoPin.A_END )
151 ioPadsSpec += [ (IoPin.EAST , None, 'sys_pll_testout_o', 'sys_pll_testout_o', 'sys_pll_testout_o' )
152 , (IoPin.EAST|IoPin.ANALOG, None, 'sys_pll_vco_o' , 'sys_pll_vco_o' , 'sys_pll_vco_o' )
153 ]
154 # I/O pads, West side.
155 ioPadsSpec += doIoPowerCap( IoPin.WEST|IoPin.A_BEGIN )
156 ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'nc_{}', ' nc({})', 'nc({})'), range(36) )
157 #ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'pwm_{}', 'pwm({})', 'pwm({})'), 2 )
158 ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'eint_{}', 'eint_{}', 'eint_{}'), 3 )
159 ioPadsSpec += [ (IoPin.WEST , None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
160 , (IoPin.WEST , None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
161 , (IoPin.WEST , None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
162 , (IoPin.WEST , None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
163 #, (IoPin.WEST , None, 'sdcard_cmd' , 'sdcard_cmd' , 'sdcard_cmd_i', 'sdcard_cmd_oe', 'sdcard_cmd_o' )
164 #, (IoPin.WEST , None, 'sdcard_clk' , 'sdcard_clk' , 'sdcard_clk' )
165 ]
166 #ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'sdcard_data_{}', 'sdcard_data({})', 'sdcard_data_i({})', 'sdcard_data_oe', 'sdcard_data_o({})'), 4 )
167 ioPadsSpec += doIoPowerCap( IoPin.WEST|IoPin.A_END )
168 # I/O pads, North side.
169 ioPadsSpec += doIoPowerCap( IoPin.NORTH|IoPin.A_BEGIN )
170 ioPadsSpec += [ (IoPin.NORTH, None, 'jtag_tms' , 'jtag_tms' , 'jtag_tms' )
171 , (IoPin.NORTH, None, 'jtag_tdi' , 'jtag_tdi' , 'jtag_tdi' )
172 , (IoPin.NORTH, None, 'jtag_tdo' , 'jtag_tdo' , 'jtag_tdo' )
173 , (IoPin.NORTH, None, 'jtag_tck' , 'jtag_tck' , 'jtag_tck' )
174 , (IoPin.NORTH, None, 'sys_clk' , 'sys_clk' , 'sys_clk' )
175 ]
176 ioPadsSpec += doIoPinVector( (IoPin.NORTH, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 )
177 ioPadsSpec += doIoPowerCap( IoPin.NORTH|IoPin.A_END )
178 # I/O pads, South side.
179 ioPadsSpec += doIoPowerCap( IoPin.SOUTH|IoPin.A_BEGIN )
180 ioPadsSpec += doIoPinVector( (IoPin.SOUTH, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,16) )
181 ioPadsSpec += [ (IoPin.SOUTH, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i', 'i2c_sda_oe', 'i2c_sda_o' ) ]
182 ioPadsSpec += [ (IoPin.SOUTH, None, 'i2c_scl' , 'i2c_scl' , 'i2c_scl' ) ]
183 ioPadsSpec += [ (IoPin.SOUTH, None, 'uart_tx', 'uart_tx', 'uart_tx' )
184 , (IoPin.SOUTH, None, 'uart_rx', 'uart_rx', 'uart_rx' )
185 , (IoPin.SOUTH, None, 'sys_rst', 'sys_rst', 'sys_rst' )
186 ]
187 ioPadsSpec += [ (IoPin.SOUTH, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' )
188 , (IoPin.SOUTH, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' )
189 , (IoPin.SOUTH, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' )
190 , (IoPin.SOUTH, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' )
191 , (IoPin.SOUTH, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' )
192 , (IoPin.SOUTH, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' )
193 ]
194 ioPadsSpec += doIoPowerCap( IoPin.SOUTH|IoPin.A_END )
195 try:
196 cell, editor = plugins.kwParseMain( **kw )
197 cell = af.getCell( 'ls180', CRL.Catalog.State.Logical )
198 if cell is None:
199 print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \
200 .format('ls180') ))
201 sys.exit(1)
202 if editor: editor.setCell( cell )
203 #ls180Conf = ChipConf( cell, ioPads=ioSpecs.ioPadsSpec )
204 ls180Conf = ChipConf( cell, ioPads=ioPadsSpec )
205 ls180Conf.cfg.etesian.bloat = 'Flexlib'
206 ls180Conf.cfg.etesian.uniformDensity = True
207 ls180Conf.cfg.etesian.aspectRatio = 1.0
208 ls180Conf.cfg.etesian.spaceMargin = 0.05
209 ls180Conf.cfg.anabatic.searchHalo = 2
210 ls180Conf.cfg.anabatic.globalIterations = 20
211 ls180Conf.cfg.anabatic.topRoutingLayer = 'METAL5'
212 ls180Conf.cfg.katana.hTracksReservedLocal = 9
213 ls180Conf.cfg.katana.vTracksReservedLocal = 5
214 ls180Conf.cfg.katana.hTracksReservedMin = 6
215 ls180Conf.cfg.katana.vTracksReservedMin = 4
216 ls180Conf.cfg.katana.runRealignStage = True
217 ls180Conf.cfg.block.spareSide = u(7*13)
218 ls180Conf.cfg.chip.supplyRailWidth = u(35)
219 ls180Conf.cfg.chip.supplyRailPitch = u(90)
220 ls180Conf.editor = editor
221 ls180Conf.useSpares = True
222 ls180Conf.useClockTree = True
223 ls180Conf.useHFNS = True
224 ls180Conf.bColumns = 2
225 ls180Conf.bRows = 2
226 ls180Conf.chipConf.name = 'chip'
227 ls180Conf.chipConf.ioPadGauge = 'LibreSOCIO'
228 ls180Conf.coreSize = (coreSizeX, coreSizeY)
229 ls180Conf.chipSize = (coreSizeX + chipBorder + u(5.0), coreSizeY + chipBorder - u(0.04) )
230 #ls180Conf.useHTree( 'core.subckt_12941_test_issuer.ti_coresync_clk' )
231 ls180Conf.useHTree( 'core.por_clk' )
232 ls180Conf.useHTree( 'jtag_tck_from_pad' )
233
234 tiPath = 'test_issuer.ti.'
235 sramDatas \
236 = [ ['test_issuer.ti.sram4k_0.spblock_512w64b8w', -2]
237 , ['test_issuer.ti.sram4k_1.spblock_512w64b8w', 3]
238 , ['test_issuer.ti.sram4k_2.spblock_512w64b8w', 2]
239 , ['test_issuer.ti.sram4k_3.spblock_512w64b8w', 3]
240 ]
241
242 ls180ToChip = CoreToChip( ls180Conf )
243 ls180ToChip.buildChip()
244 chipBuilder = Chip( ls180Conf )
245 chipBuilder.doChipFloorplan()
246
247 with UpdateSession():
248 sram = DataBase.getDB().getCell( 'spblock_512w64b8w' )
249 sramAb = sram.getAbutmentBox()
250 coreAb = cell.getAbutmentBox()
251 sliceHeight = chipBuilder.conf.sliceHeight
252 sliceStep = chipBuilder.conf.sliceStep
253 originX = coreAb.getXMin() + sramDatas[0][1]*chipBuilder.conf.sliceStep
254 for i in range(len(sramDatas)):
255 chipBuilder.placeMacro \
256 ( sramDatas[i][0]
257 , Transformation( originX
258 , coreAb.getYMax() - sramAb.getHeight() - 2*sliceHeight
259 , Transformation.Orientation.ID )
260 )
261 if i+1 < len(sramDatas):
262 originX += sramAb.getWidth() + 2*sliceHeight + sramDatas[i+1][1]*sliceStep
263 pllTransf = Transformation( coreAb.getXMax() # -u(234.0)
264 , coreAb.getYMax() - u(208.0)
265 , Transformation.Orientation.MX )
266 print( 'pllTransf={}'.format(pllTransf) )
267 chipBuilder.placeMacro( 'test_issuer.wrappll.pll' , pllTransf )
268 sys.stderr.flush()
269 sys.stdout.flush()
270 Breakpoint.stop( 99, 'After core placement.' )
271
272 rvalue = chipBuilder.doPnR()
273 chipBuilder.save()
274 CRL.Gds.save( ls180Conf.chip )
275 except Exception, e:
276 helpers.io.catch(e)
277 rvalue = False
278 sys.stdout.flush()
279 sys.stderr.flush()
280 return rvalue