more comments
[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 # XXX this is probably just por_clk not core.por_clk
232 # or, more likely, core.pllclk_clk
233 ls180Conf.useHTree( 'core.por_clk' )
234 ls180Conf.useHTree( 'jtag_tck_from_pad' )
235
236 tiPath = 'test_issuer.ti.'
237 sramDatas \
238 = [ ['test_issuer.ti.sram4k_0.spblock_512w64b8w', -2]
239 , ['test_issuer.ti.sram4k_1.spblock_512w64b8w', 3]
240 , ['test_issuer.ti.sram4k_2.spblock_512w64b8w', 2]
241 , ['test_issuer.ti.sram4k_3.spblock_512w64b8w', 3]
242 ]
243
244 ls180ToChip = CoreToChip( ls180Conf )
245 ls180ToChip.buildChip()
246 chipBuilder = Chip( ls180Conf )
247 chipBuilder.doChipFloorplan()
248
249 with UpdateSession():
250 sram = DataBase.getDB().getCell( 'spblock_512w64b8w' )
251 sramAb = sram.getAbutmentBox()
252 coreAb = cell.getAbutmentBox()
253 sliceHeight = chipBuilder.conf.sliceHeight
254 sliceStep = chipBuilder.conf.sliceStep
255 originX = coreAb.getXMin() + sramDatas[0][1]*chipBuilder.conf.sliceStep
256 for i in range(len(sramDatas)):
257 chipBuilder.placeMacro \
258 ( sramDatas[i][0]
259 , Transformation( originX
260 , coreAb.getYMax() - sramAb.getHeight() - 2*sliceHeight
261 , Transformation.Orientation.ID )
262 )
263 if i+1 < len(sramDatas):
264 originX += sramAb.getWidth() + 2*sliceHeight + sramDatas[i+1][1]*sliceStep
265 pllTransf = Transformation( coreAb.getXMax() # -u(234.0)
266 , coreAb.getYMax() - u(208.0)
267 , Transformation.Orientation.MX )
268 print( 'pllTransf={}'.format(pllTransf) )
269 chipBuilder.placeMacro( 'test_issuer.wrappll.pll' , pllTransf )
270 sys.stderr.flush()
271 sys.stdout.flush()
272 Breakpoint.stop( 99, 'After core placement.' )
273
274 rvalue = chipBuilder.doPnR()
275 chipBuilder.save()
276 CRL.Gds.save( ls180Conf.chip )
277 except Exception, e:
278 helpers.io.catch(e)
279 rvalue = False
280 sys.stdout.flush()
281 sys.stderr.flush()
282 return rvalue