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
,
19 from plugins
.alpha
.block
.matrix
import RegisterMatrix
20 from plugins
.alpha
.macro
.macro
import Macro
21 from plugins
.alpha
.block
.iospecs
import IoSpecs
22 from plugins
.alpha
.block
.block
import Block
23 from plugins
.alpha
.block
.configuration
import IoPin
, GaugeConf
24 from plugins
.alpha
.core2chip
.libresocio
import CoreToChip
25 from plugins
.alpha
.chip
.configuration
import ChipConf
26 from plugins
.alpha
.chip
.chip
import Chip
29 af
= CRL
.AllianceFramework
.get()
33 def isiterable ( pyobj
):
34 if isinstance(pyobj
,collections
.Iterable
): return True
38 def doIoPowerCap ( flags
):
40 side
= flags
& IoPin
.SIDE_MASK
41 if flags
& IoPin
.A_BEGIN
:
42 ioPadPower
= [ (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
43 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
44 , (side
, None, 'ioground_{}'.format(powerCount
), 'iovss' )
45 , (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
48 ioPadPower
= [ (side
, None, 'iopower_{}'.format(powerCount
), 'iovdd' )
49 , (side
, None, 'ioground_{}'.format(powerCount
), 'iovss' )
50 , (side
, None, 'ground_{}'.format(powerCount
), 'vss' )
51 , (side
, None, 'power_{}'.format(powerCount
), 'vdd' )
57 def doIoPinVector ( ioSpec
, bits
):
59 if not isiterable(bits
): bits
= range(bits
)
61 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "bits" is neither a width nor an iterable.'
62 , '(bits={})'.format(bits
)
68 , ioSpec
[2].format(bit
)
69 , ioSpec
[3].format(bit
)
70 , ioSpec
[4].format(bit
) ))
71 elif len(ioSpec
) == 6:
75 , ioSpec
[2].format(bit
)
76 , ioSpec
[3].format(bit
)
77 , ioSpec
[4].format(bit
)
78 , ioSpec
[5].format(bit
) ))
79 elif len(ioSpec
) == 7:
83 , ioSpec
[2].format(bit
)
84 , ioSpec
[3].format(bit
)
85 , ioSpec
[4].format(bit
)
86 , ioSpec
[5].format(bit
)
87 , ioSpec
[6].format(bit
) ))
89 raise ErrorMessage( 1, [ 'doIoPinVector(): Argument "ioSpec" ' \
90 'must have between 5 and 7 ' \
91 'fields ({})'.format(len(ioSpec
))
92 , '(ioSpec={})'.format(ioSpec
)
97 def rgetInstance ( cell
, path
):
99 Get the instance designated by path (recursively). The path argument can be
100 either a string of instance names separated by dots or directly a list of
103 if isinstance(path
,str):
104 path
= path
.split( '.' )
105 elif not isinstance(path
,list):
106 raise ErrorMessage( 1, 'rgetInstance(): "path" argument is neither ' \
107 'a string or a list ({})"' \
109 instance
= cell
.getInstance( path
[0] )
111 raise ErrorMessage( 1, 'rgetInstance(): no instance "{}" ' \
113 .format(path
[0],cell
.getName()) )
116 return rgetInstance( instance
.getMasterCell(), path
[1:] )
119 def rsetAbutmentBox ( cell
, ab
):
120 for occurrence
in cell
.getNonTerminalNetlistInstanceOccurrences():
121 masterCell
= occurrence
.getEntity().getMasterCell()
122 masterCell
.setAbutmentBox( ab
)
124 def addPllPlaceHolder ( cell
):
125 pllPlaceHolder
= Cell
.create( af
.getLibrary(0), 'pllplaceholder' )
126 pllPlaceHolder
.setAbutmentBox( Box( u(0.0), u(0.0), u(200.0), u(200.0) ))
127 pllPlaceHolder
.setTerminalNetlist( True )
128 instance
= Instance
.create( cell
, 'pllPlaceholder', pllPlaceHolder
)
132 def scriptMain (**kw
):
133 """The mandatory function to be called by Coriolis CGT/Unicorn."""
135 #helpers.setTraceLevel( 550 )
136 #Breakpoint.setStopLevel( 100 )
138 coreSize
= u(375*4.0)
139 chipSize
= u(32*90.0 + 2*214.0)
140 #coreSize = u(17*90.0)
141 #coreSize = u(59*90.0)
142 #chipBorder = u(2*214.0 + 10*13.0) + u(20*90.0)
144 pinmuxFile
= './ls180/litex_pinpads.json'
145 ioSpecs
.loadFromPinmux( pinmuxFile
)
146 # I/O pads, East side.
148 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_BEGIN
)
149 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'sdram_a_{}', 'sdram_a({})', 'sdram_a({})'), 13 )
150 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(8,16) )
151 ioPadsSpec
+= [ (IoPin
.EAST
, None, 'jtag_tms', 'jtag_tms', 'jtag_tms' )
152 , (IoPin
.EAST
, None, 'jtag_tdi', 'jtag_tdi', 'jtag_tdi' )
153 , (IoPin
.EAST
, None, 'jtag_tdo', 'jtag_tdo', 'jtag_tdo' )
154 , (IoPin
.EAST
, None, 'jtag_tck', 'jtag_tck', 'jtag_tck' )
156 ioPadsSpec
+= doIoPinVector( (IoPin
.EAST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(4) )
157 ioPadsSpec
+= doIoPowerCap( IoPin
.EAST|IoPin
.A_END
)
158 # I/O pads, West side.
159 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_BEGIN
)
160 # PWM, SDCARD taken out
161 #ioPadsSpec += [ (IoPin.WEST, None, 'pwm_1', 'pwm(1)', 'pwm(1)' ) ]
162 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'eint_{}', 'eint({})', 'eint({})'), 3 )
163 ioPadsSpec
+= [ (IoPin
.WEST
, None, 'spimaster_clk' , 'spimaster_clk' , 'spimaster_clk' )
164 , (IoPin
.WEST
, None, 'spimaster_cs_n', 'spimaster_cs_n', 'spimaster_cs_n' )
165 , (IoPin
.WEST
, None, 'spimaster_mosi', 'spimaster_mosi', 'spimaster_mosi' )
166 , (IoPin
.WEST
, None, 'spimaster_miso', 'spimaster_miso', 'spimaster_miso' )
167 #, (IoPin.WEST , None, 'sdcard_cmd' , 'sdcard_cmd' , 'sdcard_cmd_i', 'sdcard_cmd_oe', 'sdcard_cmd_o' )
168 #, (IoPin.WEST , None, 'sdcard_clk' , 'sdcard_clk' , 'sdcard_clk' )
170 #ioPadsSpec += doIoPinVector( (IoPin.WEST , None, 'sdcard_data_{}', 'sdcard_data({})', 'sdcard_data_i({})', 'sdcard_data_oe', 'sdcard_data_o({})'), 4 )
171 ioPadsSpec
+= doIoPinVector( (IoPin
.WEST
, None, 'nc_{}', 'nc({})', 'nc({})'), range(4, 25) )
172 ioPadsSpec
+= doIoPowerCap( IoPin
.WEST|IoPin
.A_END
)
173 # I/O pads, North side.
174 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_BEGIN
)
175 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dm_{}', 'sdram_dm({})', 'sdram_dm({})'), 2 )
176 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_dq_{}', 'sdram_dq({})', 'sdram_dq_i({})', 'sdram_dq_oe', 'sdram_dq_o({})'), range(0,16) )
177 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'sdram_ba_{}', 'sdram_ba({})', 'sdram_ba({})'), 2 )
178 ioPadsSpec
+= [ (IoPin
.NORTH
, None, 'sdram_clock' , 'sdram_clock' , 'sdram_clock' )
179 , (IoPin
.NORTH
, None, 'sdram_cke' , 'sdram_cke' , 'sdram_cke' )
180 , (IoPin
.NORTH
, None, 'sdram_ras_n' , 'sdram_ras_n' , 'sdram_ras_n' )
181 , (IoPin
.NORTH
, None, 'sdram_cas_n' , 'sdram_cas_n' , 'sdram_cas_n' )
182 , (IoPin
.NORTH
, None, 'sdram_we_n' , 'sdram_we_n' , 'sdram_we_n' )
183 , (IoPin
.NORTH
, None, 'sdram_cs_n' , 'sdram_cs_n' , 'sdram_cs_n' )
185 ioPadsSpec
+= doIoPinVector( (IoPin
.NORTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(25,27) )
186 ioPadsSpec
+= doIoPowerCap( IoPin
.NORTH|IoPin
.A_END
)
187 # I/O pads, South side.
188 ioPadsSpec
+= doIoPowerCap( IoPin
.SOUTH|IoPin
.A_BEGIN
)
189 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'i2c_sda_i' , 'i2c_sda_i' , 'i2c_sda_i' ) ]
190 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(27,31) )
191 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'spisdcard_clk' , 'spisdcard_clk' , 'spisdcard_clk' )
192 , (IoPin
.SOUTH
, None, 'spisdcard_cs_n', 'spisdcard_cs_n', 'spisdcard_cs_n' )
193 , (IoPin
.SOUTH
, None, 'spisdcard_mosi', 'spisdcard_mosi', 'spisdcard_mosi' )
194 , (IoPin
.SOUTH
, None, 'spisdcard_miso', 'spisdcard_miso', 'spisdcard_miso' )
196 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(31,32) )
197 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'uart_tx', 'uart_tx', 'uart_tx' )
198 , (IoPin
.SOUTH
, None, 'uart_rx', 'uart_rx', 'uart_rx' )
200 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'gpio_{}', 'gpio({})', 'gpio_i({})', 'gpio_oe({})', 'gpio_o({})'), range(0,8) )
201 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sys_clk', 'sys_clk', 'sys_clk' )
202 , (IoPin
.SOUTH
, None, 'sys_rst', 'sys_rst', 'sys_rst' )
204 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'nc_{}', 'nc({})', 'nc({})'), range(32,33) )
205 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sys_pll_18_o' , 'sys_pll_18_o' , 'sys_pll_18_o' ) ]
206 ioPadsSpec
+= doIoPinVector( (IoPin
.SOUTH
, None, 'sys_clksel_i{}', 'sys_clksel_i({})', 'sys_clksel_i({})'), 2 )
207 ioPadsSpec
+= [ (IoPin
.SOUTH
, None, 'sys_pll_lck_o' , 'sys_pll_lck_o' , 'sys_pll_lck_o' ) ]
208 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 ' \
217 if editor
: editor
.setCell( cell
)
218 ls180Conf
= ChipConf( cell
, ioPads
=ioSpecs
.ioPadsSpec
)
219 #ls180Conf = ChipConf( cell, ioPads=ioPadsSpec )
220 ls180Conf
.cfg
.etesian
.bloat
= 'nsxlib'
221 ls180Conf
.cfg
.etesian
.uniformDensity
= True
222 ls180Conf
.cfg
.etesian
.aspectRatio
= 1.0
223 ls180Conf
.cfg
.etesian
.spaceMargin
= 0.05
224 ls180Conf
.cfg
.anabatic
.searchHalo
= 2
225 ls180Conf
.cfg
.anabatic
.globalIterations
= 20
226 #ls180Conf.cfg.anabatic.topRoutingLayer = 'metal6'
227 ls180Conf
.cfg
.katana
.hTracksReservedLocal
= 6
228 ls180Conf
.cfg
.katana
.vTracksReservedLocal
= 3
229 ls180Conf
.cfg
.katana
.hTracksReservedMin
= 3
230 ls180Conf
.cfg
.katana
.vTracksReservedMin
= 1
231 ls180Conf
.cfg
.block
.spareSide
= u(7*4.0)
232 ls180Conf
.cfg
.chip
.supplyRailWidth
= u(15)
233 ls180Conf
.cfg
.chip
.supplyRailPitch
= u(45)
234 ls180Conf
.editor
= editor
235 ls180Conf
.useSpares
= True
236 ls180Conf
.useClockTree
= True
237 ls180Conf
.useHFNS
= True
238 ls180Conf
.bColumns
= 2
240 ls180Conf
.chipConf
.name
= 'chip'
241 ls180Conf
.chipConf
.ioPadGauge
= 'LibreSOCIO'
242 ls180Conf
.coreSize
= (coreSize
, coreSize
)
243 # ls180Conf.chipSize = (coreSize + chipBorder, coreSize + chipBorder)
244 ls180Conf
.chipSize
= (chipSize
, chipSize
)
246 with
UpdateSession():
247 sliceHeight
= ls180Conf
.sliceHeight
248 coreAb
= Box( 0, 0, coreSize
, coreSize
)
249 rsetAbutmentBox( cell
, coreAb
)
251 ls180ToChip
= CoreToChip( ls180Conf
)
252 ls180ToChip
.buildChip()
253 chipBuilder
= Chip( ls180Conf
)
254 chipBuilder
.doChipFloorplan()
256 with
UpdateSession():
258 # placement of SRAM blackboxes, manually
260 # Thoses ids are dependent on Yosys. They need to be adjusted
261 # whenever the design changes.
266 tiPath
= 'subckt_{}_test_issuer.subckt_1_ti.'.format(tiId
)
267 sramPaths
= [ tiPath
+'subckt_{}_sram4k_0.subckt_144_SPBlock_512W64B8W'.format(sramId
)
268 , tiPath
+'subckt_{}_sram4k_1.subckt_144_SPBlock_512W64B8W'.format(sramId
+1)
269 , tiPath
+'subckt_{}_sram4k_2.subckt_144_SPBlock_512W64B8W'.format(sramId
+2)
270 , tiPath
+'subckt_{}_sram4k_3.subckt_144_SPBlock_512W64B8W'.format(sramId
+3)
272 # each sram is named differently (yosys blackbox issue)
274 sram
= DataBase
.getDB().getCell( 'spblock512w64b8w_%i' )
276 sramAb
= sram
.getAbutmentBox()
277 coreAb
= cell
.getAbutmentBox()
278 sliceHeight
= chipBuilder
.conf
.sliceHeight
279 originX
= coreAb
.getXMin() + 2*chipBuilder
.conf
.sliceStep
280 sram
= rgetInstance( cell
, sramPaths
[i
] )
281 y
= coreAb
.getYMax() - sramAb
.getHeight() - 2*sliceHeight
282 t
= Transformation( originX
284 , Transformation
.Orientation
.ID
)
285 chipBuilder
.placeMacro ( sramPaths
[i
], t
)
286 originX
+= sramAb
.getWidth () + 3*sliceHeight
288 print (ErrorMessage( 1, 'SRAM instance %d not found.' % i
))
291 # manual placement of PLL
292 pll
= DataBase
.getDB().getCell( 'pll' )
293 # skip PLL cell for now: Alliance cannot cope with no ports
294 if pll
is None and False:
295 pll
= addPllPlaceHolder( cell
)
297 pllAb
= pll
.getAbutmentBox()
298 t
= Transformation( coreAb
.getXMax() - pllAb
.getWidth()
299 , coreAb
.getYMax() - pllAb
.getHeight()
300 , Transformation
.Orientation
.ID
)
301 pll
.setTransformation( t
)
302 pll
.setPlacementStatus( Instance
.PlacementStatus
.FIXED
)
304 #ls180Conf.placeArea = Box( coreAb.getXMin()
306 # , coreAb.getXMax() -
307 # chipBuilder.conf.sliceStep
308 # , coreAb.getYMax() -
309 # sramAb.getHeight() - 2*sliceHeight
311 #memPatterns = [ r'^mem_(?P<i>\d+)__(?P<j>[\d+])$'
312 # , r'^mem_1_(?P<i>\d+)__(?P<j>[\d+])$'
313 # , r'^mem_2_(?P<i>\d+)__(?P<j>[\d+])$'
314 # , r'^mem_3_(?P<i>\d+)__(?P<j>[\d+])$'
316 #originX += 2*sliceHeight
317 #originY = coreAb.getYMax()
318 #for i in range(len(memPatterns)):
319 # mem = RegisterMatrix( ls180Conf, cell, memPatterns[i] )
320 # originY -= mem.getHeight()
321 # mem.place( Point(originX,originY) )
322 Breakpoint
.stop( 99, 'After core placement.' )
324 rvalue
= chipBuilder
.doPnR()
326 CRL
.Gds
.save( ls180Conf
.chip
)