2 from __future__
import print_function
12 from helpers
import trace
, l
, u
, n
13 from helpers
.io
import ErrorMessage
, WarningMessage
14 from helpers
.overlay
import UpdateSession
16 from Hurricane
import Breakpoint
, DataBase
, DbU
, Transformation
, Point
, Box
, \
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
28 af
= CRL
.AllianceFramework
.get()
32 def isiterable ( pyobj
):
33 if isinstance(pyobj
,collections
.Iterable
): return True
37 def doIoPowerCap ( flags
):
39 side
= flags
& IoPin
.SIDE_MASK
40 if flags
& IoPin
.A_BEGIN
:
41 ioPadPower
= [ (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
42 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
43 , (side
, None, 'ioground_{}'.format(powerCount
), 'iovss' )
44 , (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
47 ioPadPower
= [ (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
48 , (side
, None, 'ioground_{}'.format(powerCount
), 'iovss' )
49 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
50 , (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
56 def doIoPinVector ( ioSpec
, bits
):
58 if not isiterable(bits
): bits
= range(bits
)
60 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
61 , '(bits={})'.format(bits
)
67 , ioSpec
[2].format(bit
)
68 , ioSpec
[3].format(bit
)
69 , ioSpec
[4].format(bit
) ))
70 elif len(ioSpec
) == 6:
74 , ioSpec
[2].format(bit
)
75 , ioSpec
[3].format(bit
)
76 , ioSpec
[4].format(bit
)
77 , ioSpec
[5].format(bit
) ))
78 elif len(ioSpec
) == 7:
82 , ioSpec
[2].format(bit
)
83 , ioSpec
[3].format(bit
)
84 , ioSpec
[4].format(bit
)
85 , ioSpec
[5].format(bit
)
86 , ioSpec
[6].format(bit
) ))
88 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec
))
89 , '(ioSpec={})'.format(ioSpec
)
94 def rgetInstance ( cell
, path
):
96 Get the instance designated by path (recursively). The path argument can be
97 either a string of instance names separated by dots or directly a list of
100 if isinstance(path
,str):
101 path
= path
.split( '.' )
102 elif not isinstance(path
,list):
103 raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither a string or a list ({})"' \
105 instance
= cell
.getInstance( path
[0] )
107 raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \
108 .format(path
[0],cell
.getName()) )
111 return rgetInstance( instance
.getMasterCell(), path
[1:] )
114 def rsetAbutmentBox ( cell
, ab
):
115 for occurrence
in cell
.getNonTerminalNetlistInstanceOccurrences():
116 masterCell
= occurrence
.getEntity().getMasterCell()
117 masterCell
.setAbutmentBox( ab
)
119 def addPllPlaceHolder ( cell
):
120 pllPlaceHolder
= Cell
.create( af
.getLibrary(0), 'pllplaceholder' )
121 pllPlaceHolder
.setAbutmentBox( Box( u(0.0), u(0.0), u(200.0), u(200.0) ))
122 pllPlaceHolder
.setTerminalNetlist( True )
123 instance
= Instance
.create( cell
, 'pllPlaceholder', pllPlaceHolder
)
127 def scriptMain (**kw
):
128 """The mandatory function to be called by Coriolis CGT/Unicorn."""
130 #helpers.setTraceLevel( 550 )
131 #Breakpoint.setStopLevel( 100 )
133 #coreSize = u(37*90.0)
134 coreSize
= u(59*90.0)
135 chipBorder
= u(2*214.0 + 10*13.0)
137 #pinmuxFile = './non_generated/litex_pinpads.json'
138 #pinmuxFile = './coriolis2/ls180/litex_pinpads.json'
139 #ioSpecs.loadFromPinmux( pinmuxFile )
140 # I/O pads, East side.
142 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_BEGIN
)
143 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_a_{}', 'sdram_a({})', 'sdram_a({})'), 13 )
144 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(8,16) )
145 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'jtag_tms', 'jtag_tms', 'jtag_tms' )
146 , (IoPin
.EAST
, None, 'jtag_tdi', 'jtag_tdi', 'jtag_tdi' )
147 , (IoPin
.EAST
, None, 'jtag_tdo', 'jtag_tdo', 'jtag_tdo' )
148 , (IoPin
.EAST
, None, 'jtag_tck', 'jtag_tck', 'jtag_tck' )
150 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(4) )
151 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_END
)
152 # I/O pads, West side.
153 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_BEGIN
)
154 ioPadsSpec
+= [ (IoPin
.WEST
, None, 'pwm_1', 'pwm(1)', 'pwm(1)' ) ]
155 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'eint_{}', 'eint({})', 'eint({})'), 3 )
156 ioPadsSpec
+= [ (IoPin
.WEST
, None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
157 , (IoPin
.WEST
, None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
158 , (IoPin
.WEST
, None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
159 , (IoPin
.WEST
, None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
160 , (IoPin
.WEST
, None, 'sdcard_cmd' , 'sdcard_cmd' , 'sdcard_cmd_i', 'sdcard_cmd_oe', 'sdcard_cmd_o' )
161 , (IoPin
.WEST
, None, 'sdcard_clk' , 'sdcard_clk' , 'sdcard_clk' )
163 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'sdcard_data_{}', 'sdcard_data({})', 'sdcard_data_i({})', 'sdcard_data_oe', 'sdcard_data_o({})'), 4 )
164 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(4,16) )
165 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_END
)
166 # I/O pads, North side.
167 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_BEGIN
)
168 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 )
169 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe', 'sdram_dq_o({})'), range(0,16) )
170 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
171 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' )
172 , (IoPin
.NORTH
, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' )
173 , (IoPin
.NORTH
, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' )
174 , (IoPin
.NORTH
, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' )
175 , (IoPin
.NORTH
, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' )
176 , (IoPin
.NORTH
, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' )
178 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(16,18) )
179 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_END
)
180 # I/O pads, South side.
181 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_BEGIN
)
182 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i' ) ]
183 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(18,22) )
184 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'spisdcard_clk' , 'spisdcard_clk' , 'spisdcard_clk' )
185 , (IoPin
.SOUTH
, None, 'spisdcard_cs_n', 'spisdcard_cs_n', 'spisdcard_cs_n' )
186 , (IoPin
.SOUTH
, None, 'spisdcard_mosi', 'spisdcard_mosi', 'spisdcard_mosi' )
187 , (IoPin
.SOUTH
, None, 'spisdcard_miso', 'spisdcard_miso', 'spisdcard_miso' )
189 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(22,23) )
190 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'uart_tx', 'uart_tx', 'uart_tx' )
191 , (IoPin
.SOUTH
, None, 'uart_rx', 'uart_rx', 'uart_rx' )
193 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,8) )
194 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sys_clk', 'sys_clk', 'sys_clk' )
195 , (IoPin
.SOUTH
, None, 'sys_rst', 'sys_rst', 'sys_rst' )
197 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(23,24) )
198 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sys_pll_18_o' , 'sys_pll_18_o' , 'sys_pll_18_o' ) ]
199 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 )
200 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sys_pll_lck_o' , 'sys_pll_lck_o' , 'sys_pll_lck_o' ) ]
201 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_END
)
203 cell
, editor
= plugins
.kwParseMain( **kw
)
204 cell
= af
.getCell( 'ls180', CRL
.Catalog
.State
.Logical
)
206 print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \
209 if editor
: editor
.setCell( cell
)
210 #ls180Conf = ChipConf( cell, ioPads=ioSpecs.ioPadsSpec )
211 ls180Conf
= ChipConf( cell
, ioPads
=ioPadsSpec
)
212 ls180Conf
.cfg
.etesian
.bloat
= 'nsxlib'
213 ls180Conf
.cfg
.etesian
.uniformDensity
= True
214 ls180Conf
.cfg
.etesian
.aspectRatio
= 1.0
215 ls180Conf
.cfg
.etesian
.spaceMargin
= 0.05
216 ls180Conf
.cfg
.anabatic
.searchHalo
= 2
217 ls180Conf
.cfg
.anabatic
.globalIterations
= 20
218 ls180Conf
.cfg
.anabatic
.topRoutingLayer
= 'METAL5'
219 ls180Conf
.cfg
.katana
.hTracksReservedLocal
= 6
220 ls180Conf
.cfg
.katana
.vTracksReservedLocal
= 3
221 ls180Conf
.cfg
.katana
.hTracksReservedMin
= 3
222 ls180Conf
.cfg
.katana
.vTracksReservedMin
= 1
223 ls180Conf
.cfg
.block
.spareSide
= u(7*13)
224 ls180Conf
.cfg
.chip
.supplyRailWidth
= u(35)
225 ls180Conf
.cfg
.chip
.supplyRailPitch
= u(90)
226 ls180Conf
.editor
= editor
227 ls180Conf
.useSpares
= True
228 ls180Conf
.useClockTree
= True
229 ls180Conf
.useHFNS
= True
230 ls180Conf
.bColumns
= 2
232 ls180Conf
.chipConf
.name
= 'chip'
233 ls180Conf
.chipConf
.ioPadGauge
= 'LibreSOCIO'
234 ls180Conf
.coreSize
= (coreSize
, coreSize
)
235 ls180Conf
.chipSize
= (coreSize
+ chipBorder
, coreSize
+ chipBorder
)
237 with
UpdateSession():
238 sliceHeight
= ls180Conf
.sliceHeight
239 coreAb
= Box( 0, 0, coreSize
, coreSize
)
240 rsetAbutmentBox( cell
, coreAb
)
242 ls180ToChip
= CoreToChip( ls180Conf
)
243 ls180ToChip
.buildChip()
244 chipBuilder
= Chip( ls180Conf
)
245 chipBuilder
.doChipFloorplan()
247 with
UpdateSession():
248 # Thoses ids are dependent on Yosys. They need to be adjusted whenever
249 # the design changes.
254 tiPath
= 'subckt_{}_test_issuer.subckt_1_ti.'.format(tiId
)
255 sramPaths
= [ tiPath
+'subckt_{}_sram4k_0.subckt_144_SPBlock_512W64B8W'.format(sramId
)
256 , tiPath
+'subckt_{}_sram4k_1.subckt_144_SPBlock_512W64B8W'.format(sramId
+1)
257 , tiPath
+'subckt_{}_sram4k_2.subckt_144_SPBlock_512W64B8W'.format(sramId
+2)
258 , tiPath
+'subckt_{}_sram4k_3.subckt_144_SPBlock_512W64B8W'.format(sramId
+3)
260 sram
= DataBase
.getDB().getCell( 'SPBlock_512W64B8W' )
262 raise ErrorMessage( 1, 'SRAM instance "{}" not found.'.format(sramPaths
[i
]) )
263 sramAb
= sram
.getAbutmentBox()
264 coreAb
= cell
.getAbutmentBox()
265 sliceHeight
= chipBuilder
.conf
.sliceHeight
266 originX
= coreAb
.getXMin() + 2*chipBuilder
.conf
.sliceStep
268 sram
= rgetInstance( cell
, sramPaths
[i
] )
269 chipBuilder
.placeMacro \
271 , Transformation( originX
272 , coreAb
.getYMax() - sramAb
.getHeight() - 2*sliceHeight
273 , Transformation
.Orientation
.ID
)
275 originX
+= sramAb
.getWidth () + 3*sliceHeight
276 pll
= addPllPlaceHolder( cell
)
277 pllAb
= pll
.getAbutmentBox()
278 pll
.setTransformation( Transformation( coreAb
.getXMax() - pllAb
.getWidth()
279 , coreAb
.getYMax() - pllAb
.getHeight()
280 , Transformation
.Orientation
.ID
) )
281 pll
.setPlacementStatus( Instance
.PlacementStatus
.FIXED
)
282 #ls180Conf.placeArea = Box( coreAb.getXMin()
284 # , coreAb.getXMax() - chipBuilder.conf.sliceStep
285 # , coreAb.getYMax() - sramAb.getHeight() - 2*sliceHeight
287 #memPatterns = [ r'^mem_(?P<i>\d+)__(?P<j>[\d+])$'
288 # , r'^mem_1_(?P<i>\d+)__(?P<j>[\d+])$'
289 # , r'^mem_2_(?P<i>\d+)__(?P<j>[\d+])$'
290 # , r'^mem_3_(?P<i>\d+)__(?P<j>[\d+])$'
292 #originX += 2*sliceHeight
293 #originY = coreAb.getYMax()
294 #for i in range(len(memPatterns)):
295 # mem = RegisterMatrix( ls180Conf, cell, memPatterns[i] )
296 # originY -= mem.getHeight()
297 # mem.place( Point(originX,originY) )
298 Breakpoint
.stop( 99, 'After core placement.' )
300 rvalue
= chipBuilder
.doPnR()
302 CRL
.Gds
.save( ls180Conf
.chip
)