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