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
26 #from plugins.alpha.utils import rgetInstanceMatching
29 af
= CRL
.AllianceFramework
.get()
35 twoGrid
= DbU
.fromGrid( 2 )
42 def isiterable ( pyobj
):
43 if isinstance(pyobj
,collections
.Iterable
): return True
47 def doIoPowerCap ( flags
):
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
), 'vss' )
54 , (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
57 ioPadPower
= [ (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
58 , (side
, None, 'ioground_{}'.format(powerCount
), 'vss' )
59 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
60 , (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
66 def doIoPinVector ( ioSpec
, bits
):
68 if not isiterable(bits
): bits
= range(bits
)
70 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
71 , '(bits={})'.format(bits
)
77 , ioSpec
[2].format(bit
)
78 , ioSpec
[3].format(bit
)
79 , ioSpec
[4].format(bit
) ))
80 elif len(ioSpec
) == 6:
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:
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
) ))
98 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" must have between 5 and 7 fields ({})'.format(len(ioSpec
))
99 , '(ioSpec={})'.format(ioSpec
)
104 def rgetInstance ( cell
, path
):
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
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 ({})"' \
115 instance
= cell
.getInstance( path
[0] )
117 raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" in cell "{}"' \
118 .format(path
[0],cell
.getName()) )
121 return rgetInstance( instance
.getMasterCell(), path
[1:] )
124 def rsetAbutmentBox ( cell
, ab
):
125 for occurrence
in cell
.getNonTerminalNetlistInstanceOccurrences():
126 masterCell
= occurrence
.getEntity().getMasterCell()
127 masterCell
.setAbutmentBox( ab
)
130 def scriptMain (**kw
):
131 """The mandatory function to be called by Coriolis CGT/Unicorn."""
133 #helpers.setTraceLevel( 550 )
134 #Breakpoint.setStopLevel( 100 )
136 coreSizeX
= u(51*90.0)
137 coreSizeY
= u(56*90.0)
138 chipBorder
= u(2*214.0 + 8*13.0)
141 # this should work fine, tested on nsxlib
142 cwd
= os
.path
.split(os
.path
.abspath(__file__
))[0]
143 pinmuxFile
= '%s/non_generated/litex_pinpads.json' % cwd
144 # actual contents auto-generated and listed at:
145 # http://libre-soc.org/180nm_Oct2020/ls180/
146 ioSpecs
.loadFromPinmux( pinmuxFile
)
148 # XXX ioPadsSpec created but not used. saves time, saves errors. see
149 # wiki page for contents: http://libre-soc.org/180nm_Oct2020/ls180/
150 # if *not* using the auto-generated ioSpecs, ioPadsSpec should, really,
151 # be made exactly the same. which is more work.
153 # I/O pads, East side.
155 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_BEGIN
)
156 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' )
157 , (IoPin
.EAST
, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' )
158 , (IoPin
.EAST
, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' )
160 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_a_{}' , 'sdram_a({})' , 'sdram_a({})'), 13 )
161 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
162 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 )
163 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(0,2) )
164 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_END
)
165 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'sys_pll_testout_o', 'sys_pll_testout_o', 'sys_pll_testout_o' )
166 , (IoPin
.EAST|IoPin
.ANALOG
, None, 'sys_pll_vco_o' , 'sys_pll_vco_o' , 'sys_pll_vco_o' )
169 # I/O pads, North side.
170 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_BEGIN
)
171 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'jtag_tms' , 'jtag_tms' , 'jtag_tms' )
172 , (IoPin
.NORTH
, None, 'jtag_tdi' , 'jtag_tdi' , 'jtag_tdi' )
173 , (IoPin
.NORTH
, None, 'jtag_tdo' , 'jtag_tdo' , 'jtag_tdo' )
174 , (IoPin
.NORTH
, None, 'jtag_tck' , 'jtag_tck' , 'jtag_tck' )
176 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(2,19) )
177 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe({})', 'sdram_dq_o({})'), range(0,16) )
178 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 )
179 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'sys_clk' , 'sys_clk' , 'sys_clk' ) ]
180 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_END
)
182 # I/O pads, West side.
183 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_BEGIN
)
184 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'nc_{}', ' nc({})', 'nc({})'), range(19,36) )
185 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'eint_{}', 'eint_{}', 'eint_{}'), 3 )
186 ioPadsSpec
+= [ (IoPin
.WEST
, None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
187 , (IoPin
.WEST
, None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
188 , (IoPin
.WEST
, None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
189 , (IoPin
.WEST
, None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
191 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_END
)
193 # I/O pads, South side.
194 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_BEGIN
)
195 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,16) )
196 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i', 'i2c_sda_oe', 'i2c_sda_o' ) ]
197 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_scl' , 'i2c_scl' , 'i2c_scl' ) ]
198 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'uart_tx', 'uart_tx', 'uart_tx' )
199 , (IoPin
.SOUTH
, None, 'uart_rx', 'uart_rx', 'uart_rx' )
200 , (IoPin
.SOUTH
, None, 'sys_rst', 'sys_rst', 'sys_rst' )
202 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' )
203 , (IoPin
.SOUTH
, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' )
204 , (IoPin
.SOUTH
, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' )
206 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_END
)
209 cell
, editor
= plugins
.kwParseMain( **kw
)
210 cell
= af
.getCell( 'ls180', CRL
.Catalog
.State
.Logical
)
212 print( ErrorMessage( 2, 'doDesign.scriptMain(): Unable to load cell "{}".' \
215 if editor
: editor
.setCell( cell
)
216 # use auto-generated (but from non_generated) io pads specs
217 # works fine with soclayout nsxlib, should work perfectly fine
219 ls180Conf
= ChipConf( cell
, ioPads
=ioSpecs
.ioPadsSpec
)
220 #ls180Conf = ChipConf( cell, ioPads=ioPadsSpec )
221 ls180Conf
.cfg
.etesian
.bloat
= 'Flexlib'
222 ls180Conf
.cfg
.etesian
.uniformDensity
= True
223 ls180Conf
.cfg
.etesian
.aspectRatio
= 1.0
224 ls180Conf
.cfg
.etesian
.spaceMargin
= 0.05
225 ls180Conf
.cfg
.anabatic
.searchHalo
= 3
226 ls180Conf
.cfg
.anabatic
.globalIterations
= 20
227 ls180Conf
.cfg
.anabatic
.topRoutingLayer
= 'METAL5'
228 ls180Conf
.cfg
.katana
.hTracksReservedLocal
= 11
229 ls180Conf
.cfg
.katana
.vTracksReservedLocal
= 7
230 ls180Conf
.cfg
.katana
.hTracksReservedMin
= 9
231 ls180Conf
.cfg
.katana
.vTracksReservedMin
= 5
232 ls180Conf
.cfg
.katana
.runRealignStage
= True
233 ls180Conf
.cfg
.block
.spareSide
= u(7*13)
234 ls180Conf
.cfg
.chip
.supplyRailWidth
= u(35)
235 ls180Conf
.cfg
.chip
.supplyRailPitch
= u(90)
236 ls180Conf
.editor
= editor
237 ls180Conf
.useSpares
= True
238 ls180Conf
.useClockTree
= True
239 ls180Conf
.useHFNS
= True
240 ls180Conf
.bColumns
= 2
242 ls180Conf
.chipConf
.name
= 'chip'
243 ls180Conf
.chipConf
.ioPadGauge
= 'LibreSOCIO'
244 ls180Conf
.coreSize
= (coreSizeX
, coreSizeY
)
245 ls180Conf
.chipSize
= (coreSizeX
+ chipBorder
+ u(5.0), coreSizeY
+ chipBorder
- u(0.04) )
246 ls180Conf
.chipLogos
= [ 'C4MLogo_norm'
247 , 'libresoc_logo_norm'
248 , 'sorbonne_logo_norm'
251 ls180Conf
.useHTree( 'core.pll_clk' )
252 ls180Conf
.useHTree( 'jtag_tck_from_pad' )
254 tiPath
= 'test_issuer.ti.'
256 = [ ['test_issuer.ti.sram4k_0.spblock_512w64b8w', -2]
257 , ['test_issuer.ti.sram4k_1.spblock_512w64b8w', 2]
258 , ['test_issuer.ti.sram4k_2.spblock_512w64b8w', 2]
259 , ['test_issuer.ti.sram4k_3.spblock_512w64b8w', 2]
262 ls180ToChip
= CoreToChip( ls180Conf
)
263 ls180ToChip
.buildChip()
264 chipBuilder
= Chip( ls180Conf
)
265 chipBuilder
.doChipFloorplan()
267 with
UpdateSession():
268 sram
= DataBase
.getDB().getCell( 'spblock_512w64b8w' )
269 sramAb
= sram
.getAbutmentBox()
270 coreAb
= cell
.getAbutmentBox()
271 sliceHeight
= chipBuilder
.conf
.sliceHeight
272 sliceStep
= chipBuilder
.conf
.sliceStep
273 originX
= coreAb
.getXMin() + sramDatas
[0][1]*chipBuilder
.conf
.sliceStep
274 for i
in range(len(sramDatas
)):
275 chipBuilder
.placeMacro \
277 , Transformation( originX
278 , coreAb
.getYMax() - sramAb
.getHeight() - 2*sliceHeight
279 , Transformation
.Orientation
.ID
)
281 if i
+1 < len(sramDatas
):
282 originX
+= sramAb
.getWidth() + 2*sliceHeight
+ sramDatas
[i
+1][1]*sliceStep
283 pllTransf
= Transformation( coreAb
.getXMax() # -u(234.0)
284 , coreAb
.getYMax() - u(208.0)
285 , Transformation
.Orientation
.MX
)
286 print( 'pllTransf={}'.format(pllTransf
) )
287 chipBuilder
.placeMacro( 'test_issuer.wrappll.pll' , pllTransf
)
290 Breakpoint
.stop( 99, 'After core placement.' )
292 rvalue
= chipBuilder
.doPnR()
294 CRL
.Gds
.save( ls180Conf
.chip
)