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
.block
.spares
import Spares
24 from plugins
.alpha
.core2chip
.libresocio
import CoreToChip
25 from plugins
.alpha
.chip
.configuration
import ChipConf
26 from plugins
.alpha
.chip
.chip
import Chip
27 #from plugins.alpha.utils import rgetInstanceMatching
30 af
= CRL
.AllianceFramework
.get()
36 twoGrid
= DbU
.fromGrid( 2 )
43 def isiterable ( pyobj
):
44 if isinstance(pyobj
,collections
.Iterable
): return True
48 def doIoPowerCap ( flags
):
50 side
= flags
& IoPin
.SIDE_MASK
51 if flags
& IoPin
.A_BEGIN
:
52 ioPadPower
= [ (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
53 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
54 , (side
, None, 'ioground_{}'.format(powerCount
), 'vss' )
55 , (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
58 ioPadPower
= [ (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
59 , (side
, None, 'ioground_{}'.format(powerCount
), 'vss' )
60 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
61 , (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
67 def doIoPinVector ( ioSpec
, bits
):
69 if not isiterable(bits
): bits
= range(bits
)
71 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
72 , '(bits={})'.format(bits
)
78 , ioSpec
[2].format(bit
)
79 , ioSpec
[3].format(bit
)
80 , ioSpec
[4].format(bit
) ))
81 elif len(ioSpec
) == 6:
85 , ioSpec
[2].format(bit
)
86 , ioSpec
[3].format(bit
)
87 , ioSpec
[4].format(bit
)
88 , ioSpec
[5].format(bit
) ))
89 elif len(ioSpec
) == 7:
93 , ioSpec
[2].format(bit
)
94 , ioSpec
[3].format(bit
)
95 , ioSpec
[4].format(bit
)
96 , ioSpec
[5].format(bit
)
97 , ioSpec
[6].format(bit
) ))
99 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec
))
100 , '(ioSpec={})'.format(ioSpec
)
105 def rgetInstance ( cell
, path
):
107 Get the instance designated by path (recursively). The path argument can be
108 either a string of instance names separated by dots or directly a list of
111 if isinstance(path
,str):
112 path
= path
.split( '.' )
113 elif not isinstance(path
,list):
114 raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither a string or a list ({})"' \
116 instance
= cell
.getInstance( path
[0] )
118 raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \
119 .format(path
[0],cell
.getName()) )
122 return rgetInstance( instance
.getMasterCell(), path
[1:] )
125 def rsetAbutmentBox ( cell
, ab
):
126 for occurrence
in cell
.getNonTerminalNetlistInstanceOccurrences():
127 masterCell
= occurrence
.getEntity().getMasterCell()
128 masterCell
.setAbutmentBox( ab
)
131 def scriptMain (**kw
):
132 """The mandatory function to be called by Coriolis CGT/Unicorn."""
134 #helpers.setTraceLevel( 550 )
135 #Breakpoint.setStopLevel( 100 )
137 coreSizeX
= u(51*90.0)
138 coreSizeY
= u(56*90.0)
139 chipBorder
= u(2*214.0 + 8*13.0)
142 # this should work fine, tested on nsxlib
143 cwd
= os
.path
.split(os
.path
.abspath(__file__
))[0]
144 pinmuxFile
= '%s/non_generated/litex_pinpads.json' % cwd
145 # actual contents auto-generated and listed at:
146 # http://libre-soc.org/180nm_Oct2020/ls180/
147 ioSpecs
.loadFromPinmux( pinmuxFile
)
149 # XXX ioPadsSpec created but not used. saves time, saves errors. see
150 # wiki page for contents: http://libre-soc.org/180nm_Oct2020/ls180/
151 # if *not* using the auto-generated ioSpecs, ioPadsSpec should, really,
152 # be made exactly the same. which is more work.
154 # I/O pads, East side.
156 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_BEGIN
)
157 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' )
158 , (IoPin
.EAST
, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' )
159 , (IoPin
.EAST
, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' )
161 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_a_{}' , 'sdram_a({})' , 'sdram_a({})'), 13 )
162 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
163 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 )
164 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(0,2) )
165 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_END
)
166 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'sys_pll_testout_o', 'sys_pll_testout_o', 'sys_pll_testout_o' )
167 , (IoPin
.EAST|IoPin
.ANALOG
, None, 'sys_pll_vco_o' , 'sys_pll_vco_o' , 'sys_pll_vco_o' )
170 # I/O pads, North side.
171 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_BEGIN
)
172 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'jtag_tms' , 'jtag_tms' , 'jtag_tms' )
173 , (IoPin
.NORTH
, None, 'jtag_tdi' , 'jtag_tdi' , 'jtag_tdi' )
174 , (IoPin
.NORTH
, None, 'jtag_tdo' , 'jtag_tdo' , 'jtag_tdo' )
175 , (IoPin
.NORTH
, None, 'jtag_tck' , 'jtag_tck' , 'jtag_tck' )
177 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(2,19) )
178 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe({})', 'sdram_dq_o({})'), range(0,16) )
179 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 )
180 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'sys_clk' , 'sys_clk' , 'sys_clk' ) ]
181 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_END
)
183 # I/O pads, West side.
184 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_BEGIN
)
185 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'nc_{}', ' nc({})', 'nc({})'), range(19,36) )
186 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'eint_{}', 'eint_{}', 'eint_{}'), 3 )
187 ioPadsSpec
+= [ (IoPin
.WEST
, None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
188 , (IoPin
.WEST
, None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
189 , (IoPin
.WEST
, None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
190 , (IoPin
.WEST
, None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
192 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_END
)
194 # I/O pads, South side.
195 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_BEGIN
)
196 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,16) )
197 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i', 'i2c_sda_oe', 'i2c_sda_o' ) ]
198 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_scl' , 'i2c_scl' , 'i2c_scl' ) ]
199 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'uart_tx', 'uart_tx', 'uart_tx' )
200 , (IoPin
.SOUTH
, None, 'uart_rx', 'uart_rx', 'uart_rx' )
201 , (IoPin
.SOUTH
, None, 'sys_rst', 'sys_rst', 'sys_rst' )
203 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' )
204 , (IoPin
.SOUTH
, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' )
205 , (IoPin
.SOUTH
, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' )
207 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_END
)
210 cell
, editor
= plugins
.kwParseMain( **kw
)
211 cell
= af
.getCell( 'ls180', CRL
.Catalog
.State
.Logical
)
213 print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \
216 if editor
: editor
.setCell( cell
)
217 # use auto-generated (but from non_generated) io pads specs
218 # works fine with soclayout nsxlib, should work perfectly fine
220 ls180Conf
= ChipConf( cell
, ioPads
=ioSpecs
.ioPadsSpec
)
221 #ls180Conf = ChipConf( cell, ioPads=ioPadsSpec )
222 ls180Conf
.cfg
.etesian
.bloat
= 'Flexlib'
223 ls180Conf
.cfg
.etesian
.uniformDensity
= True
224 ls180Conf
.cfg
.etesian
.aspectRatio
= 1.0
225 ls180Conf
.cfg
.etesian
.spaceMargin
= 0.05
226 ls180Conf
.cfg
.anabatic
.searchHalo
= 3
227 ls180Conf
.cfg
.anabatic
.globalIterations
= 20
228 ls180Conf
.cfg
.anabatic
.topRoutingLayer
= 'METAL5'
229 ls180Conf
.cfg
.katana
.hTracksReservedLocal
= 11
230 ls180Conf
.cfg
.katana
.vTracksReservedLocal
= 8
231 ls180Conf
.cfg
.katana
.hTracksReservedMin
= 9
232 ls180Conf
.cfg
.katana
.vTracksReservedMin
= 6
233 ls180Conf
.cfg
.katana
.runRealignStage
= True
234 ls180Conf
.cfg
.katana
.trackFill
= 2
235 ls180Conf
.cfg
.block
.spareSide
= u(7*13)
236 ls180Conf
.cfg
.chip
.supplyRailWidth
= u(35)
237 ls180Conf
.cfg
.chip
.supplyRailPitch
= u(90)
238 ls180Conf
.editor
= editor
239 ls180Conf
.useSpares
= True
240 ls180Conf
.useClockTree
= True
241 ls180Conf
.useHFNS
= True
242 ls180Conf
.bColumns
= 2
244 ls180Conf
.chipConf
.name
= 'chip'
245 ls180Conf
.chipConf
.ioPadGauge
= 'LibreSOCIO'
246 ls180Conf
.coreSize
= (coreSizeX
, coreSizeY
)
247 ls180Conf
.chipSize
= (coreSizeX
+ chipBorder
+ u(5.0), coreSizeY
+ chipBorder
- u(0.04) )
248 ls180Conf
.chipLogos
= [ 'C4MLogo_norm'
249 , 'libresoc_logo_norm'
250 , 'sorbonne_logo_norm'
253 ls180Conf
.useHTree( 'core.pll_clk', Spares
.HEAVY_LEAF_LOAD
)
254 ls180Conf
.useHTree( 'jtag_tck_from_pad' )
256 tiPath
= 'test_issuer.ti.'
258 = [ ['test_issuer.ti.sram4k_0.spblock_512w64b8w', -2]
259 , ['test_issuer.ti.sram4k_1.spblock_512w64b8w', 2]
260 , ['test_issuer.ti.sram4k_2.spblock_512w64b8w', 2]
261 , ['test_issuer.ti.sram4k_3.spblock_512w64b8w', 2]
264 ls180ToChip
= CoreToChip( ls180Conf
)
265 ls180ToChip
.buildChip()
266 chipBuilder
= Chip( ls180Conf
)
267 chipBuilder
.doChipFloorplan()
269 with
UpdateSession():
270 sram
= DataBase
.getDB().getCell( 'spblock_512w64b8w' )
271 sramAb
= sram
.getAbutmentBox()
272 coreAb
= cell
.getAbutmentBox()
273 sliceHeight
= chipBuilder
.conf
.sliceHeight
274 sliceStep
= chipBuilder
.conf
.sliceStep
275 originX
= coreAb
.getXMin() + sramDatas
[0][1]*chipBuilder
.conf
.sliceStep
276 for i
in range(len(sramDatas
)):
277 chipBuilder
.placeMacro \
279 , Transformation( originX
280 , coreAb
.getYMax() - sramAb
.getHeight() - 2*sliceHeight
281 , Transformation
.Orientation
.ID
)
283 if i
+1 < len(sramDatas
):
284 originX
+= sramAb
.getWidth() + 2*sliceHeight
+ sramDatas
[i
+1][1]*sliceStep
285 pllTransf
= Transformation( coreAb
.getXMax() # -u(234.0)
286 , coreAb
.getYMax() - u(208.0)
287 , Transformation
.Orientation
.MX
)
288 print( 'pllTransf={}'.format(pllTransf
) )
289 chipBuilder
.placeMacro( 'test_issuer.wrappll.pll' , pllTransf
)
292 Breakpoint
.stop( 99, 'After core placement.' )
294 rvalue
= chipBuilder
.doPnR()
296 CRL
.Gds
.save( ls180Conf
.chip
)