track files copied from caravel
diff --git a/ngspice/digital_pll/digital_pll/digital_pll.spice b/ngspice/digital_pll/digital_pll/digital_pll.spice new file mode 100644 index 0000000..cd88d48 --- /dev/null +++ b/ngspice/digital_pll/digital_pll/digital_pll.spice
@@ -0,0 +1,43 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* All-digital Frequency-locked loop +*--------------------------------------------------------------------------- +* To make this simulatable, the circuit is broken into the ring oscillator +* and controller, separately, with the controller converted into an xspice +* model. +* +* For simplicity, the DCO mode has been removed, so no external trim with +* multiplexer. Also no multiplexer on the internal reset. +*--------------------------------------------------------------------------- + +.include "digital_pll_controller.xspice" +.include "ring_osc2x13.spice" + +.subckt digital_pll vdd vss reset osc clockp1 clockp0 div4 div3 div2 div1 div0 + +X0 vdd vss clockp0 div0 div1 div2 div3 div4 osc reset trim0 trim1 trim2 trim3 ++ trim4 trim5 trim6 trim7 trim8 trim9 trim10 trim11 trim12 trim13 trim14 ++ trim15 trim16 trim17 trim18 trim19 trim20 trim21 trim22 trim23 trim24 ++ trim25 digital_pll_controller + +X1 vdd vss clockp0 clockp1 reset trim0 trim1 trim2 trim3 trim4 trim5 trim6 trim7 ++ trim8 trim9 trim10 trim11 trim12 trim13 trim14 trim15 trim16 trim17 trim18 ++ trim19 trim20 trim21 trim22 trim23 trim24 trim25 ring_osc2x13 + +.ends + +
diff --git a/ngspice/digital_pll/digital_pll/digital_pll_controller.xspice b/ngspice/digital_pll/digital_pll/digital_pll_controller.xspice new file mode 100644 index 0000000..cbb0343 --- /dev/null +++ b/ngspice/digital_pll/digital_pll/digital_pll_controller.xspice
@@ -0,0 +1,497 @@ +* XSpice netlist created from SPICE and liberty sources by spi2xspice.py +* SPICE netlist created from verilog structural netlist module digital_pll_controller by vlog2Spice (qflow) +* +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +******* EOF +** End of included library /home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice +.subckt digital_pll_controller a_VPB a_VGND a_clock a_div_0_ a_div_1_ a_div_2_ a_div_3_ a_div_4_ a_osc a_reset a_trim_0_ a_trim_1_ a_trim_2_ a_trim_3_ a_trim_4_ a_trim_5_ a_trim_6_ a_trim_7_ a_trim_8_ a_trim_9_ a_trim_10_ a_trim_11_ a_trim_12_ a_trim_13_ a_trim_14_ a_trim_15_ a_trim_16_ a_trim_17_ a_trim_18_ a_trim_19_ a_trim_20_ a_trim_21_ a_trim_22_ a_trim_23_ a_trim_24_ a_trim_25_ +Asky130_fd_sc_hd__buf_1_insert11 [_64_] _64__bF$buf0 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert10 [_64_] _64__bF$buf1 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert9 [_64_] _64__bF$buf2 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert8 [_64_] _64__bF$buf3 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert7 [_4_] _4__bF$buf0 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert6 [_4_] _4__bF$buf1 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert5 [_4_] _4__bF$buf2 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__buf_1_insert4 [_4_] _4__bF$buf3 d_lut_sky130_fd_sc_hd__buf_1 +Asky130_fd_sc_hd__clkbuf_1_insert3 [clock] clock_bF$buf0 d_lut_sky130_fd_sc_hd__clkbuf_1 +Asky130_fd_sc_hd__clkbuf_1_insert2 [clock] clock_bF$buf1 d_lut_sky130_fd_sc_hd__clkbuf_1 +Asky130_fd_sc_hd__clkbuf_1_insert1 [clock] clock_bF$buf2 d_lut_sky130_fd_sc_hd__clkbuf_1 +Asky130_fd_sc_hd__clkbuf_1_insert0 [clock] clock_bF$buf3 d_lut_sky130_fd_sc_hd__clkbuf_1 +A_218_ [tint_1_ tint_0_] _194_ d_lut_sky130_fd_sc_hd__nor2_1 +A_219_ [tint_3_ tint_2_] _195_ d_lut_sky130_fd_sc_hd__nor2_1 +A_220_ [_194_ _195_] _196_ d_lut_sky130_fd_sc_hd__nand2_1 +A_221_ [tint_4_ _196_] _197_ d_lut_sky130_fd_sc_hd__nor2_1 +A_222_ [_197_] _217__0_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_223_ [tval_0_] _198_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_224_ [oscbuf_1_ oscbuf_2_] _199_ d_lut_sky130_fd_sc_hd__nor2_1 +A_225_ [oscbuf_1_ oscbuf_2_] _200_ d_lut_sky130_fd_sc_hd__nand2_1 +A_226_ [_200_] _201_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_227_ [_199_ _201_] _202_ d_lut_sky130_fd_sc_hd__or2_2 +A_228_ [_202_] _203_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_229_ [_203_ prep_0_] _204_ d_lut_sky130_fd_sc_hd__nand2_1 +A_230_ [prep_1_ prep_2_] _205_ d_lut_sky130_fd_sc_hd__nand2_1 +A_231_ [_205_ _204_] _206_ d_lut_sky130_fd_sc_hd__nor2_1 +A_232_ [count1_4_] _207_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_233_ [count0_4_] _208_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_234_ [_207_ _208_] _209_ d_lut_sky130_fd_sc_hd__nor2_1 +A_235_ [count1_4_ count0_4_] _210_ d_lut_sky130_fd_sc_hd__nor2_1 +A_236_ [_210_ _209_] _211_ d_lut_sky130_fd_sc_hd__or2_2 +A_237_ [count1_3_ count0_3_] _212_ d_lut_sky130_fd_sc_hd__and2_2 +A_238_ [count1_3_ count0_3_] _213_ d_lut_sky130_fd_sc_hd__nor2_1 +A_239_ [_213_] _214_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_240_ [count1_2_ count0_2_] _215_ d_lut_sky130_fd_sc_hd__and2_2 +A_241_ [_214_ _215_ _212_] _216_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_242_ [count1_1_ count0_1_] _5_ d_lut_sky130_fd_sc_hd__nand2_1 +A_243_ [count1_0_ count0_0_] _6_ d_lut_sky130_fd_sc_hd__nand2_1 +A_244_ [count1_1_ count0_1_] _7_ d_lut_sky130_fd_sc_hd__nor2_1 +A_245_ [_6_ _7_ _5_] _8_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_246_ [count1_2_ count0_2_] _9_ d_lut_sky130_fd_sc_hd__nor2_1 +A_247_ [_9_ _215_] _10_ d_lut_sky130_fd_sc_hd__nor2_1 +A_248_ [_213_ _212_] _11_ d_lut_sky130_fd_sc_hd__nor2_1 +A_249_ [_10_ _11_ _8_] _12_ d_lut_sky130_fd_sc_hd__nand3_1 +A_250_ [_12_ _216_ _211_] _13_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_251_ [_209_ _210_ _216_ _12_] _14_ d_lut_sky130_fd_sc_hd__o211a_1 +A_252_ [_14_ _13_ div_4_] _15_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_253_ [div_4_] _16_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_254_ [_211_ _12_ _216_] _17_ d_lut_sky130_fd_sc_hd__nand3_1 +A_255_ [_17_ _16_ _209_] _18_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_256_ [_15_ _18_] _19_ d_lut_sky130_fd_sc_hd__nand2_1 +A_257_ [div_3_] _20_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_258_ [_215_] _21_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_259_ [_10_ _8_] _22_ d_lut_sky130_fd_sc_hd__nand2_1 +A_260_ [_212_ _213_ _21_ _22_] _23_ d_lut_sky130_fd_sc_hd__o211ai_1 +A_261_ [_6_ _7_ _5_] _24_ d_lut_sky130_fd_sc_hd__o21a_1 +A_262_ [_9_ _24_ _215_] _25_ d_lut_sky130_fd_sc_hd__o21bai_1 +A_263_ [_25_ _11_] _26_ d_lut_sky130_fd_sc_hd__nand2_1 +A_264_ [_26_ _20_ _23_] _27_ d_lut_sky130_fd_sc_hd__nand3_1 +A_265_ [div_2_ _8_ _10_] _28_ d_lut_sky130_fd_sc_hd__xnor3_4 +A_266_ [_22_ _21_ _11_] _29_ d_lut_sky130_fd_sc_hd__nand3_1 +A_267_ [_21_ _22_ _212_ _213_] _30_ d_lut_sky130_fd_sc_hd__o2bb2ai_1 +A_268_ [_30_ div_3_ _29_] _31_ d_lut_sky130_fd_sc_hd__nand3_1 +A_269_ [div_0_] _32_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_270_ [count1_0_ count0_0_] _33_ d_lut_sky130_fd_sc_hd__xor2_1 +A_271_ [_33_ _32_] _34_ d_lut_sky130_fd_sc_hd__and2_2 +A_272_ [div_1_] _35_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_273_ [count1_1_ count0_1_] _36_ d_lut_sky130_fd_sc_hd__or2_2 +A_274_ [_36_ _5_] _37_ d_lut_sky130_fd_sc_hd__nand2_1 +A_275_ [_35_ _6_ _37_] _38_ d_lut_sky130_fd_sc_hd__xnor3_4 +A_276_ [_32_ _33_] _39_ d_lut_sky130_fd_sc_hd__nor2_1 +A_277_ [_34_ _39_ _38_] _40_ d_lut_sky130_fd_sc_hd__nor3_1 +A_278_ [_40_ _27_ _28_ _31_] _41_ d_lut_sky130_fd_sc_hd__nand4_1 +A_279_ [_41_ _19_] _42_ d_lut_sky130_fd_sc_hd__or2_2 +A_280_ [_36_ count1_0_ count0_0_ _5_] _43_ d_lut_sky130_fd_sc_hd__nand4_1 +A_281_ [count1_1_ count0_1_] _44_ d_lut_sky130_fd_sc_hd__and2_2 +A_282_ [_7_ _44_ _6_] _45_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_283_ [_45_ _43_ _35_] _46_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_284_ [_45_ _43_ _35_] _47_ d_lut_sky130_fd_sc_hd__nand3_1 +A_285_ [_33_ _32_] _48_ d_lut_sky130_fd_sc_hd__nand2_1 +A_286_ [_47_ _48_ _46_] _49_ d_lut_sky130_fd_sc_hd__a21o_2 +A_287_ [_27_ _31_ _28_ _49_] _50_ d_lut_sky130_fd_sc_hd__nand4_1 +A_288_ [_215_ _9_ _24_] _51_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_289_ [_51_ _22_ div_2_] _52_ d_lut_sky130_fd_sc_hd__a21boi_0 +A_290_ [_27_ _52_] _53_ d_lut_sky130_fd_sc_hd__nand2_1 +A_291_ [_50_ _31_ _53_ _19_] _54_ d_lut_sky130_fd_sc_hd__a31oi_1 +A_292_ [_12_ div_4_ _210_ _216_] _55_ d_lut_sky130_fd_sc_hd__nand4_1 +A_293_ [_55_] _56_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_294_ [tval_0_ tval_1_] _57_ d_lut_sky130_fd_sc_hd__nor2_1 +A_295_ [_197_ _57_] _58_ d_lut_sky130_fd_sc_hd__nand2_1 +A_296_ [_58_] _59_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_297_ [tval_0_ _59_ _56_ _54_ _42_] _60_ d_lut_sky130_fd_sc_hd__o221ai_1 +A_298_ [_15_ _18_] _61_ d_lut_sky130_fd_sc_hd__and2_2 +A_299_ [_50_ _31_ _53_] _62_ d_lut_sky130_fd_sc_hd__nand3_1 +A_300_ [_62_ _61_] _63_ d_lut_sky130_fd_sc_hd__nand2_1 +A_301_ [tint_4_] _64_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_302_ [tval_0_ tval_1_] _65_ d_lut_sky130_fd_sc_hd__nand2_1 +A_303_ [tint_1_ tint_0_] _66_ d_lut_sky130_fd_sc_hd__nand2_1 +A_304_ [_65_ _66_] _67_ d_lut_sky130_fd_sc_hd__nor2_1 +A_305_ [_67_ tint_3_ tint_2_] _68_ d_lut_sky130_fd_sc_hd__nand3_1 +A_306_ [_64__bF$buf3 _68_] _69_ d_lut_sky130_fd_sc_hd__nor2_1 +A_307_ [_69_] _70_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_308_ [_63_ tval_0_ _55_ _70_] _71_ d_lut_sky130_fd_sc_hd__nand4_1 +A_309_ [tval_0_ _42_ _206_ _71_ _60_] _72_ d_lut_sky130_fd_sc_hd__o2111ai_1 +A_310_ [_198_ _206_ _72_] _3__0_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_311_ [tval_1_] _73_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_312_ [_65_] _74_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_313_ [_57_ _74_] _75_ d_lut_sky130_fd_sc_hd__nor2_1 +A_314_ [_59_ _75_ _56_ _54_ _42_] _76_ d_lut_sky130_fd_sc_hd__o221ai_1 +A_315_ [_75_ _69_] _77_ d_lut_sky130_fd_sc_hd__nor2_1 +A_316_ [_63_ _55_ _77_] _78_ d_lut_sky130_fd_sc_hd__nand3_1 +A_317_ [tval_1_ _42_ _206_ _78_ _76_] _79_ d_lut_sky130_fd_sc_hd__o2111ai_1 +A_318_ [_73_ _206_ _79_] _3__1_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_319_ [tint_0_] _80_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_320_ [_206_] _81_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_321_ [_62_ _61_ _56_] _82_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_322_ [_80_ _65_] _83_ d_lut_sky130_fd_sc_hd__nor2_1 +A_323_ [tint_0_ _74_] _84_ d_lut_sky130_fd_sc_hd__nor2_1 +A_324_ [_83_ _84_ _70_] _85_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_325_ [_82_ _85_ _81_] _86_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_326_ [_63_ _55_] _87_ d_lut_sky130_fd_sc_hd__nand2_1 +A_327_ [_41_ _19_] _88_ d_lut_sky130_fd_sc_hd__nor2_1 +A_328_ [_57_ _80_] _89_ d_lut_sky130_fd_sc_hd__nand2_1 +A_329_ [_57_] _90_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_330_ [_90_ tint_0_] _91_ d_lut_sky130_fd_sc_hd__nand2_1 +A_331_ [_91_ _89_ _197_] _92_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_332_ [_88_ _80_] _93_ d_lut_sky130_fd_sc_hd__nand2_1 +A_333_ [_88_ _92_ _93_ _87_] _94_ d_lut_sky130_fd_sc_hd__o211ai_1 +A_334_ [_80_ _81_ _86_ _94_] _3__2_ d_lut_sky130_fd_sc_hd__a22oi_1 +A_335_ [tint_1_] _95_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_336_ [tint_1_ _83_] _96_ d_lut_sky130_fd_sc_hd__nor2_1 +A_337_ [_67_ _96_ _70_] _97_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_338_ [_82_ _97_ _81_] _98_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_339_ [_194_ _57_] _99_ d_lut_sky130_fd_sc_hd__nand2_1 +A_340_ [_89_ tint_1_] _100_ d_lut_sky130_fd_sc_hd__nand2_1 +A_341_ [_99_ _100_ _59_] _101_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_342_ [_88_ _95_] _102_ d_lut_sky130_fd_sc_hd__nand2_1 +A_343_ [_88_ _101_ _102_ _87_] _103_ d_lut_sky130_fd_sc_hd__o211ai_1 +A_344_ [_95_ _81_ _98_ _103_] _3__3_ d_lut_sky130_fd_sc_hd__a22oi_1 +A_345_ [tint_2_] _104_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_346_ [_194_ _57_ _104_] _105_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_347_ [tint_2_ _99_] _106_ d_lut_sky130_fd_sc_hd__nor2_1 +A_348_ [_106_ _105_ _58_] _107_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_349_ [_88_ tint_2_] _108_ d_lut_sky130_fd_sc_hd__nand2_1 +A_350_ [_107_ _88_ _56_ _54_ _108_] _109_ d_lut_sky130_fd_sc_hd__o221ai_1 +A_351_ [_67_ tint_2_] _110_ d_lut_sky130_fd_sc_hd__nand2_1 +A_352_ [_65_ _66_ _104_] _111_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_353_ [_111_ _110_ _69_] _112_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_354_ [_63_ _55_ _112_] _113_ d_lut_sky130_fd_sc_hd__nand3_1 +A_355_ [_109_ _206_ _113_] _114_ d_lut_sky130_fd_sc_hd__nand3_1 +A_356_ [_104_ _206_ _114_] _3__4_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_357_ [tint_3_] _115_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_358_ [tint_4_ _68_] _116_ d_lut_sky130_fd_sc_hd__nor2_1 +A_359_ [_115_ _110_ _116_] _117_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_360_ [_82_ _117_ _81_] _118_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_361_ [_90_ _196_] _119_ d_lut_sky130_fd_sc_hd__nor2_1 +A_362_ [_115_ _106_] _120_ d_lut_sky130_fd_sc_hd__nor2_1 +A_363_ [_119_ _120_] _121_ d_lut_sky130_fd_sc_hd__nor2_1 +A_364_ [_59_ _121_] _122_ d_lut_sky130_fd_sc_hd__nor2_1 +A_365_ [_88_ _115_] _123_ d_lut_sky130_fd_sc_hd__nand2_1 +A_366_ [_88_ _122_ _123_ _87_] _124_ d_lut_sky130_fd_sc_hd__o211ai_1 +A_367_ [_115_ _81_ _118_ _124_] _3__5_ d_lut_sky130_fd_sc_hd__a22oi_1 +A_368_ [_56_ _54_ _206_ _119_ _42_] _125_ d_lut_sky130_fd_sc_hd__o2111a_1 +A_369_ [_68_ _64__bF$buf2] _126_ d_lut_sky130_fd_sc_hd__nand2_1 +A_370_ [_206_ _126_] _127_ d_lut_sky130_fd_sc_hd__nand2_1 +A_371_ [_87_ _127_ _64__bF$buf1 _125_] _3__6_ d_lut_sky130_fd_sc_hd__o22ai_1 +A_372_ [prep_0_ _203_] _2__0_ d_lut_sky130_fd_sc_hd__or2_2 +A_373_ [prep_1_] _128_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_374_ [_128_ _203_ _204_] _2__1_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_375_ [_202_ prep_2_] _129_ d_lut_sky130_fd_sc_hd__nand2_1 +A_376_ [_128_ _202_ _129_] _2__2_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_377_ [count0_0_] _130_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_378_ [_202_ count1_0_] _131_ d_lut_sky130_fd_sc_hd__nand2_1 +A_379_ [_130_ _202_ _131_] _1__0_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_380_ [count0_1_] _132_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_381_ [_202_ count1_1_] _133_ d_lut_sky130_fd_sc_hd__nand2_1 +A_382_ [_132_ _202_ _133_] _1__1_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_383_ [count0_2_] _134_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_384_ [_202_ count1_2_] _135_ d_lut_sky130_fd_sc_hd__nand2_1 +A_385_ [_134_ _202_ _135_] _1__2_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_386_ [_203_ count0_3_] _136_ d_lut_sky130_fd_sc_hd__nand2_1 +A_387_ [_202_ count1_3_] _137_ d_lut_sky130_fd_sc_hd__nand2_1 +A_388_ [_136_ _137_] _1__3_ d_lut_sky130_fd_sc_hd__nand2_1 +A_389_ [_202_ count1_4_] _138_ d_lut_sky130_fd_sc_hd__nand2_1 +A_390_ [_208_ _202_ _138_] _1__4_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_391_ [_132_ _130_] _139_ d_lut_sky130_fd_sc_hd__nor2_1 +A_392_ [_139_] _140_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_393_ [_134_ _140_] _141_ d_lut_sky130_fd_sc_hd__nor2_1 +A_394_ [_141_ count0_3_] _142_ d_lut_sky130_fd_sc_hd__nand2_1 +A_395_ [_142_] _143_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_396_ [_143_ count0_4_] _144_ d_lut_sky130_fd_sc_hd__nand2_1 +A_397_ [_144_ count0_0_ _202_] _0__0_ d_lut_sky130_fd_sc_hd__nand3_1 +A_398_ [_132_ _130_] _145_ d_lut_sky130_fd_sc_hd__nand2_1 +A_399_ [_140_ _145_] _146_ d_lut_sky130_fd_sc_hd__nand2_1 +A_400_ [_144_ _146_ _203_] _0__1_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_401_ [_134_ _139_] _147_ d_lut_sky130_fd_sc_hd__xor2_1 +A_402_ [_144_ _147_ _203_] _0__2_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_403_ [count0_3_ _141_ _202_] _148_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_404_ [_143_ _208_ _148_] _0__3_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_405_ [_142_ _208_ _203_] _0__4_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_406_ [tint_3_ tint_2_] _149_ d_lut_sky130_fd_sc_hd__nand2_1 +A_407_ [_149_ _64__bF$buf0] _217__1_ d_lut_sky130_fd_sc_hd__nand2_1 +A_408_ [tint_3_ _104_] _150_ d_lut_sky130_fd_sc_hd__nor2_1 +A_409_ [_150_] _151_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_410_ [_66_ _151_] _152_ d_lut_sky130_fd_sc_hd__nor2_1 +A_411_ [_195_ tint_1_ _80_ _64__bF$buf3] _153_ d_lut_sky130_fd_sc_hd__nand4_1 +A_412_ [_195_] _154_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_413_ [tint_4_ _154_] _155_ d_lut_sky130_fd_sc_hd__nor2_1 +A_414_ [_155_ _95_] _217__6_ d_lut_sky130_fd_sc_hd__nand2_1 +A_415_ [_217__6_ _153_] _156_ d_lut_sky130_fd_sc_hd__nand2_1 +A_416_ [_80_ _64__bF$buf2 tint_1_] _157_ d_lut_sky130_fd_sc_hd__nand3_1 +A_417_ [_157_ _151_] _158_ d_lut_sky130_fd_sc_hd__nor2_1 +A_418_ [_158_] _159_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_419_ [_66_ _154_] _160_ d_lut_sky130_fd_sc_hd__nor2_1 +A_420_ [_95_ _150_ _160_] _161_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_421_ [tint_4_ _161_ _159_] _162_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_422_ [_156_ _162_] _217__5_ d_lut_sky130_fd_sc_hd__nor2_1 +A_423_ [_217__5_] _163_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_424_ [_64__bF$buf1 _152_ _163_] _217__2_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_425_ [_155_] _217__3_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_426_ [_95_ tint_0_] _164_ d_lut_sky130_fd_sc_hd__nand2_1 +A_427_ [_104_ tint_3_] _165_ d_lut_sky130_fd_sc_hd__nand2_1 +A_428_ [_164_ _165_] _166_ d_lut_sky130_fd_sc_hd__nor2_1 +A_429_ [_166_ _64__bF$buf0] _167_ d_lut_sky130_fd_sc_hd__nand2_1 +A_430_ [_152_ _64__bF$buf3] _168_ d_lut_sky130_fd_sc_hd__nand2_1 +A_431_ [_194_] _169_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_432_ [_165_ _169_] _170_ d_lut_sky130_fd_sc_hd__nor2_1 +A_433_ [_170_ _64__bF$buf2] _171_ d_lut_sky130_fd_sc_hd__nand2_1 +A_434_ [_168_ _171_] _172_ d_lut_sky130_fd_sc_hd__nand2_1 +A_435_ [_172_ _163_] _217__9_ d_lut_sky130_fd_sc_hd__nor2_1 +A_436_ [_217__9_ _167_] _173_ d_lut_sky130_fd_sc_hd__nand2_1 +A_437_ [_173_] _217__4_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_438_ [tint_4_ _149_ _169_] _174_ d_lut_sky130_fd_sc_hd__nor3_1 +A_439_ [tint_4_ _66_ _165_] _175_ d_lut_sky130_fd_sc_hd__nor3_1 +A_440_ [_165_ _157_] _176_ d_lut_sky130_fd_sc_hd__nor2_1 +A_441_ [_174_ _175_ _176_ _173_] _217__7_ d_lut_sky130_fd_sc_hd__nor4_1 +A_442_ [_104_ _194_ _115_ _64__bF$buf1] _217__8_ d_lut_sky130_fd_sc_hd__o211ai_1 +A_443_ [_156_] _217__10_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_444_ [_176_ _173_] _217__11_ d_lut_sky130_fd_sc_hd__nor2_1 +A_445_ [tint_4_ _161_] _177_ d_lut_sky130_fd_sc_hd__nor2_1 +A_446_ [_156_ _177_] _217__12_ d_lut_sky130_fd_sc_hd__nor2_1 +A_447_ [_217__9_] _178_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_448_ [_175_ _174_] _179_ d_lut_sky130_fd_sc_hd__nor2_1 +A_449_ [_179_ _167_] _180_ d_lut_sky130_fd_sc_hd__nand2_1 +A_450_ [tint_4_ _149_ _164_ _157_ _165_] _181_ d_lut_sky130_fd_sc_hd__o32ai_1 +A_451_ [_180_ _181_ _178_] _217__13_ d_lut_sky130_fd_sc_hd__nor3_1 +A_452_ [_95_ _80_ _104_ _115_ _64__bF$buf0] _217__14_ d_lut_sky130_fd_sc_hd__a311oi_1 +A_453_ [_154_ _66_ _169_ _151_] _182_ d_lut_sky130_fd_sc_hd__o22ai_1 +A_454_ [tint_4_ _95_ _149_] _183_ d_lut_sky130_fd_sc_hd__nor3_1 +A_455_ [tint_4_ _195_ _66_ _183_] _184_ d_lut_sky130_fd_sc_hd__a31oi_1 +A_456_ [_184_] _185_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_457_ [_181_ _185_] _186_ d_lut_sky130_fd_sc_hd__nor2_1 +A_458_ [_217__9_ _167_ _179_ _186_] _187_ d_lut_sky130_fd_sc_hd__nand4_1 +A_459_ [tint_4_ _182_ _187_] _217__15_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_460_ [_194_ _195_ _64__bF$buf3] _217__16_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_461_ [_64__bF$buf2 _161_] _188_ d_lut_sky130_fd_sc_hd__nor2_1 +A_462_ [_95_ tint_0_ _64__bF$buf1 _151_] _189_ d_lut_sky130_fd_sc_hd__nor4_1 +A_463_ [_188_ _189_ _187_] _217__17_ d_lut_sky130_fd_sc_hd__nor3_1 +A_464_ [_64__bF$buf0 _195_] _217__18_ d_lut_sky130_fd_sc_hd__nor2_1 +A_465_ [_149_ _66_ _64__bF$buf3] _217__19_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_466_ [_150_ _160_ tint_4_] _190_ d_lut_sky130_fd_sc_hd__o21ai_0 +A_467_ [_186_ _179_ _190_] _191_ d_lut_sky130_fd_sc_hd__nand3_1 +A_468_ [_170_ tint_4_ _166_] _192_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_469_ [_192_ _153_ _217__6_] _193_ d_lut_sky130_fd_sc_hd__nand3_1 +A_470_ [_172_ _193_ _162_ _191_] _217__20_ d_lut_sky130_fd_sc_hd__nor4_1 +A_471_ [_195_ _95_ _64__bF$buf2] _217__21_ d_lut_sky130_fd_sc_hd__a21oi_1 +A_472_ [_188_ _187_] _217__22_ d_lut_sky130_fd_sc_hd__nor2_1 +A_473_ [_191_ _173_] _217__24_ d_lut_sky130_fd_sc_hd__nor2_1 +A_474_ [_187_] _217__25_ d_lut_sky130_fd_sc_hd__clkinv_1 +A_475_ [reset] _4_ d_lut_sky130_fd_sc_hd__clkinv_2 +A_476_ [tint_4_] trim_23_ d_lut_sky130_fd_sc_hd__buf_2 +A_477_ [_217__0_] trim_0_ d_lut_sky130_fd_sc_hd__buf_2 +A_478_ [_217__1_] trim_1_ d_lut_sky130_fd_sc_hd__buf_2 +A_479_ [_217__2_] trim_2_ d_lut_sky130_fd_sc_hd__buf_2 +A_480_ [_217__3_] trim_3_ d_lut_sky130_fd_sc_hd__buf_2 +A_481_ [_217__4_] trim_4_ d_lut_sky130_fd_sc_hd__buf_2 +A_482_ [_217__5_] trim_5_ d_lut_sky130_fd_sc_hd__buf_2 +A_483_ [_217__6_] trim_6_ d_lut_sky130_fd_sc_hd__buf_2 +A_484_ [_217__7_] trim_7_ d_lut_sky130_fd_sc_hd__buf_2 +A_485_ [_217__8_] trim_8_ d_lut_sky130_fd_sc_hd__buf_2 +A_486_ [_217__9_] trim_9_ d_lut_sky130_fd_sc_hd__buf_2 +A_487_ [_217__10_] trim_10_ d_lut_sky130_fd_sc_hd__buf_2 +A_488_ [_217__11_] trim_11_ d_lut_sky130_fd_sc_hd__buf_2 +A_489_ [_217__12_] trim_12_ d_lut_sky130_fd_sc_hd__buf_2 +A_490_ [_217__13_] trim_13_ d_lut_sky130_fd_sc_hd__buf_2 +A_491_ [_217__14_] trim_14_ d_lut_sky130_fd_sc_hd__buf_2 +A_492_ [_217__15_] trim_15_ d_lut_sky130_fd_sc_hd__buf_2 +A_493_ [_217__16_] trim_16_ d_lut_sky130_fd_sc_hd__buf_2 +A_494_ [_217__17_] trim_17_ d_lut_sky130_fd_sc_hd__buf_2 +A_495_ [_217__18_] trim_18_ d_lut_sky130_fd_sc_hd__buf_2 +A_496_ [_217__19_] trim_19_ d_lut_sky130_fd_sc_hd__buf_2 +A_497_ [_217__20_] trim_20_ d_lut_sky130_fd_sc_hd__buf_2 +A_498_ [_217__21_] trim_21_ d_lut_sky130_fd_sc_hd__buf_2 +A_499_ [_217__22_] trim_22_ d_lut_sky130_fd_sc_hd__buf_2 +A_500_ [_217__24_] trim_24_ d_lut_sky130_fd_sc_hd__buf_2 +A_501_ [_217__25_] trim_25_ d_lut_sky130_fd_sc_hd__buf_2 +A_502_ _0__0_ clock_bF$buf3 NULL ~_4__bF$buf3 NULL NULL ddflop +A_503_ _0__1_ clock_bF$buf2 NULL ~_4__bF$buf2 NULL NULL ddflop +A_504_ _0__2_ clock_bF$buf1 NULL ~_4__bF$buf1 NULL NULL ddflop +A_505_ _0__3_ clock_bF$buf0 NULL ~_4__bF$buf0 NULL NULL ddflop +A_506_ _0__4_ clock_bF$buf3 NULL ~_4__bF$buf3 NULL NULL ddflop +A_507_ _1__0_ clock_bF$buf2 NULL ~_4__bF$buf2 NULL NULL ddflop +A_508_ _1__1_ clock_bF$buf1 NULL ~_4__bF$buf1 NULL NULL ddflop +A_509_ _1__2_ clock_bF$buf0 NULL ~_4__bF$buf0 NULL NULL ddflop +A_510_ _1__3_ clock_bF$buf3 NULL ~_4__bF$buf3 NULL NULL ddflop +A_511_ _1__4_ clock_bF$buf2 NULL ~_4__bF$buf2 NULL NULL ddflop +A_512_ osc clock_bF$buf1 NULL ~_4__bF$buf1 NULL NULL ddflop +A_513_ oscbuf_0_ clock_bF$buf0 NULL ~_4__bF$buf0 NULL NULL ddflop +A_514_ oscbuf_1_ clock_bF$buf3 NULL ~_4__bF$buf3 NULL NULL ddflop +A_515_ _2__0_ clock_bF$buf2 NULL ~_4__bF$buf2 NULL NULL ddflop +A_516_ _2__1_ clock_bF$buf1 NULL ~_4__bF$buf1 NULL NULL ddflop +A_517_ _2__2_ clock_bF$buf0 NULL ~_4__bF$buf0 NULL NULL ddflop +A_518_ _3__0_ clock_bF$buf3 NULL ~_4__bF$buf3 NULL NULL ddflop +A_519_ _3__1_ clock_bF$buf2 NULL ~_4__bF$buf2 NULL NULL ddflop +A_520_ _3__2_ clock_bF$buf1 NULL ~_4__bF$buf1 NULL NULL ddflop +A_521_ _3__3_ clock_bF$buf0 NULL ~_4__bF$buf0 NULL NULL ddflop +A_522_ _3__4_ clock_bF$buf3 NULL ~_4__bF$buf3 NULL NULL ddflop +A_523_ _3__5_ clock_bF$buf2 NULL ~_4__bF$buf2 NULL NULL ddflop +A_524_ _3__6_ clock_bF$buf1 NULL ~_4__bF$buf1 NULL NULL ddflop + +.model todig_1v95 adc_bridge(in_high=1.3 in_low=0.65 rise_delay=500p fall_delay=500p) +.model toana_1v95 dac_bridge(out_high=1.95 out_low=0) + +.model ddflop d_dff(ic=0 rise_delay=50p fall_delay=50p) +.model dzero d_pulldown(load=250f) +.model done d_pullup(load=250f) + +AA2D1 [a_VPB] [VPB] todig_1v95 +AA2D2 [a_VGND] [VGND] todig_1v95 +AA2D3 [a_clock] [clock] todig_1v95 +AA2D4 [a_div_0_] [div_0_] todig_1v95 +AA2D5 [a_div_1_] [div_1_] todig_1v95 +AA2D6 [a_div_2_] [div_2_] todig_1v95 +AA2D7 [a_div_3_] [div_3_] todig_1v95 +AA2D8 [a_div_4_] [div_4_] todig_1v95 +AA2D9 [a_osc] [osc] todig_1v95 +AA2D10 [a_reset] [reset] todig_1v95 +AD2A1 [trim_0_] [a_trim_0_] toana_1v95 +AD2A2 [trim_1_] [a_trim_1_] toana_1v95 +AD2A3 [trim_2_] [a_trim_2_] toana_1v95 +AD2A4 [trim_3_] [a_trim_3_] toana_1v95 +AD2A5 [trim_4_] [a_trim_4_] toana_1v95 +AD2A6 [trim_5_] [a_trim_5_] toana_1v95 +AD2A7 [trim_6_] [a_trim_6_] toana_1v95 +AD2A8 [trim_7_] [a_trim_7_] toana_1v95 +AD2A9 [trim_8_] [a_trim_8_] toana_1v95 +AD2A10 [trim_9_] [a_trim_9_] toana_1v95 +AD2A11 [trim_10_] [a_trim_10_] toana_1v95 +AD2A12 [trim_11_] [a_trim_11_] toana_1v95 +AD2A13 [trim_12_] [a_trim_12_] toana_1v95 +AD2A14 [trim_13_] [a_trim_13_] toana_1v95 +AD2A15 [trim_14_] [a_trim_14_] toana_1v95 +AD2A16 [trim_15_] [a_trim_15_] toana_1v95 +AD2A17 [trim_16_] [a_trim_16_] toana_1v95 +AD2A18 [trim_17_] [a_trim_17_] toana_1v95 +AD2A19 [trim_18_] [a_trim_18_] toana_1v95 +AD2A20 [trim_19_] [a_trim_19_] toana_1v95 +AD2A21 [trim_20_] [a_trim_20_] toana_1v95 +AD2A22 [trim_21_] [a_trim_21_] toana_1v95 +AD2A23 [trim_22_] [a_trim_22_] toana_1v95 +AD2A24 [trim_23_] [a_trim_23_] toana_1v95 +AD2A25 [trim_24_] [a_trim_24_] toana_1v95 +AD2A26 [trim_25_] [a_trim_25_] toana_1v95 + +.ends + +* sky130_fd_sc_hd__nand2_2 (!A) | (!B) +.model d_lut_sky130_fd_sc_hd__nand2_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1110") +* sky130_fd_sc_hd__inv_2 (!A) +.model d_lut_sky130_fd_sc_hd__inv_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "10") +* sky130_fd_sc_hd__nor2_2 (!A&!B) +.model d_lut_sky130_fd_sc_hd__nor2_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1000") +* sky130_fd_sc_hd__conb_1 1 +* sky130_fd_sc_hd__buf_1 (A) +.model d_lut_sky130_fd_sc_hd__buf_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "01") +* sky130_fd_sc_hd__clkbuf_1 (A) +.model d_lut_sky130_fd_sc_hd__clkbuf_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "01") +* sky130_fd_sc_hd__nor2_1 (!A&!B) +.model d_lut_sky130_fd_sc_hd__nor2_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1000") +* sky130_fd_sc_hd__nand2_1 (!A) | (!B) +.model d_lut_sky130_fd_sc_hd__nand2_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1110") +* sky130_fd_sc_hd__clkinv_1 (!A) +.model d_lut_sky130_fd_sc_hd__clkinv_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "10") +* sky130_fd_sc_hd__or2_2 (A) | (B) +.model d_lut_sky130_fd_sc_hd__or2_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "0111") +* sky130_fd_sc_hd__and2_2 (A&B) +.model d_lut_sky130_fd_sc_hd__and2_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "0001") +* sky130_fd_sc_hd__a21oi_1 (!A1&!B1) | (!A2&!B1) +.model d_lut_sky130_fd_sc_hd__a21oi_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11100000") +* sky130_fd_sc_hd__o21ai_0 (!A1&!A2) | (!B1) +.model d_lut_sky130_fd_sc_hd__o21ai_0 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11111000") +* sky130_fd_sc_hd__nand3_1 (!A) | (!B) | (!C) +.model d_lut_sky130_fd_sc_hd__nand3_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11111110") +* sky130_fd_sc_hd__o211a_1 (A1&B1&C1) | (A2&B1&C1) +.model d_lut_sky130_fd_sc_hd__o211a_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "0000000000000111") +* sky130_fd_sc_hd__o211ai_1 (!A1&!A2) | (!B1) | (!C1) +.model d_lut_sky130_fd_sc_hd__o211ai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1111111111111000") +* sky130_fd_sc_hd__o21a_1 (A1&B1) | (A2&B1) +.model d_lut_sky130_fd_sc_hd__o21a_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "00000111") +* sky130_fd_sc_hd__o21bai_1 (!A1&!A2) | (B1_N) +.model d_lut_sky130_fd_sc_hd__o21bai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "10001111") +* sky130_fd_sc_hd__xnor3_4 (!A&!B&!C) | (A&B&!C) | (A&!B&C) | (!A&B&C) +.model d_lut_sky130_fd_sc_hd__xnor3_4 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "10010110") +* sky130_fd_sc_hd__o2bb2ai_1 (!B1&!B2) | (A1_N&A2_N) +.model d_lut_sky130_fd_sc_hd__o2bb2ai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1111000100010001") +* sky130_fd_sc_hd__xor2_1 (A&!B) | (!A&B) +.model d_lut_sky130_fd_sc_hd__xor2_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "0110") +* sky130_fd_sc_hd__nor3_1 (!A&!B&!C) +.model d_lut_sky130_fd_sc_hd__nor3_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "10000000") +* sky130_fd_sc_hd__nand4_1 (!A) | (!B) | (!C) | (!D) +.model d_lut_sky130_fd_sc_hd__nand4_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1111111111111110") +* sky130_fd_sc_hd__a21o_2 (A1&A2) | (B1) +.model d_lut_sky130_fd_sc_hd__a21o_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "00011111") +* sky130_fd_sc_hd__a21boi_0 (!A1&B1_N) | (!A2&B1_N) +.model d_lut_sky130_fd_sc_hd__a21boi_0 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "00001110") +* sky130_fd_sc_hd__a31oi_1 (!A1&!B1) | (!A2&!B1) | (!A3&!B1) +.model d_lut_sky130_fd_sc_hd__a31oi_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1111111000000000") +* sky130_fd_sc_hd__o221ai_1 (!B1&!B2) | (!A1&!A2) | (!C1) +.model d_lut_sky130_fd_sc_hd__o221ai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11111111111111111111100010001000") +* sky130_fd_sc_hd__o2111ai_1 (!A1&!A2) | (!B1) | (!C1) | (!D1) +.model d_lut_sky130_fd_sc_hd__o2111ai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11111111111111111111111111111000") +* sky130_fd_sc_hd__a22oi_1 (!A1&!B1) | (!A1&!B2) | (!A2&!B1) | (!A2&!B2) +.model d_lut_sky130_fd_sc_hd__a22oi_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1110111011100000") +* sky130_fd_sc_hd__o2111a_1 (A1&B1&C1&D1) | (A2&B1&C1&D1) +.model d_lut_sky130_fd_sc_hd__o2111a_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "00000000000000000000000000000111") +* sky130_fd_sc_hd__o22ai_1 (!B1&!B2) | (!A1&!A2) +.model d_lut_sky130_fd_sc_hd__o22ai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1111100010001000") +* sky130_fd_sc_hd__nor4_1 (!A&!B&!C&!D) +.model d_lut_sky130_fd_sc_hd__nor4_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "1000000000000000") +* sky130_fd_sc_hd__o32ai_1 (!A1&!A2&!A3) | (!B1&!B2) +.model d_lut_sky130_fd_sc_hd__o32ai_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11111111100000001000000010000000") +* sky130_fd_sc_hd__a311oi_1 (!A1&!B1&!C1) | (!A2&!B1&!C1) | (!A3&!B1&!C1) +.model d_lut_sky130_fd_sc_hd__a311oi_1 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "11111110000000000000000000000000") +* sky130_fd_sc_hd__clkinv_2 (!A) +.model d_lut_sky130_fd_sc_hd__clkinv_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "10") +* sky130_fd_sc_hd__buf_2 (A) +.model d_lut_sky130_fd_sc_hd__buf_2 d_lut (rise_delay=50p fall_delay=50p input_load=250f ++ table_values "01") +* sky130_fd_sc_hd__dfrtp_2 IQ +* sky130_fd_sc_hd__dfrtp_1 IQ +* sky130_fd_sc_hd__dfrtp_4 IQ +* sky130_fd_sc_hd__diode_2 (no function) +.end
diff --git a/ngspice/digital_pll/digital_pll/digital_pll_tb.spice b/ngspice/digital_pll/digital_pll/digital_pll_tb.spice new file mode 100644 index 0000000..c3d89ce --- /dev/null +++ b/ngspice/digital_pll/digital_pll/digital_pll_tb.spice
@@ -0,0 +1,64 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Complete Digital PLL testbench +*-------------------------------- + +.lib "/home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice" tt + +.include "/home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice" + +.include "digital_pll.spice" + +.option TEMP=27 +* .option RELTOL=1.0E-2 + +* Instantiate the digital PLL + +X0 vdd vss reset osc clkp1 clkp0 div4 div3 div2 div1 div0 digital_pll + +* Power supply (note that all logic is 1.8V here) + +V0 vdd vss PWL(0.0 0.0 25n 1.8) +V1 vss 0 0.0 + +* Fixed divider value (connect resistors to power or ground) +* divider value = 16 (10MHz * 16 = 160MHz clock) + +R0 div4 vdd 1 +R1 div3 gnd 1 +R2 div2 gnd 1 +R3 div1 gnd 1 +R4 div0 gnd 1 + +* Run oscillator at 10MHz +* Because DFFs don't handle reclocking well, keep the edges sharp. + +V2 osc vss PULSE(0.0 1.8 5n 10p 10p 50n 100n) + +* Reset pulse +V3 reset vss PWL(0.0 1.8 0.1u 1.8 0.101u 0.0) + +* Transient analysis. Note that trim updates every four cycles, or about +* three updates per microsecond. To update all 17 trim bits requires +* 6us. + +.control +tran 1n 8u +plot V(osc) +plot V(clkp0) V(clkp1) +.endc +.end
diff --git a/ngspice/digital_pll/digital_pll/inverter_tb.spi b/ngspice/digital_pll/digital_pll/inverter_tb.spi new file mode 100644 index 0000000..36d5c18 --- /dev/null +++ b/ngspice/digital_pll/digital_pll/inverter_tb.spi
@@ -0,0 +1,37 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Simple testbench mainly to check SPICE model conversion from CDL +* Plots the transient response of the smallest inverter in the HD standard cell library + +.lib "/home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice" tt +.include "/home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice" + +* .option TEMP=27 + +X0 in vss vss vdd vdd out sky130_fd_sc_hd__inv_1 + +V0 vdd vss PWL(0n 0.0 30n 1.8) +V1 vss 0 0.0 + +Vin in vss PWL(0n 0.0 100n 0.0 500n 1.8) + +* Transient analysis +.control +tran 1n 1u +plot V(in) V(out) +.endc +.end
diff --git a/ngspice/digital_pll/digital_pll/ring_osc2x13.spice b/ngspice/digital_pll/digital_pll/ring_osc2x13.spice new file mode 100644 index 0000000..5553f2c --- /dev/null +++ b/ngspice/digital_pll/digital_pll/ring_osc2x13.spice
@@ -0,0 +1,264 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* SPICE netlist created from verilog structural netlist module ring_osc2x13 by vlog2Spice (qflow) +* Warning: This file contains <> array delimiters in net names_ +* Note: Library sky130_fd_sc_hd_spice has been removed; reference library as an +* include file from the testbench instead_ + +.subckt ring_osc2x13 VPB VGND clockp<0> clockp<1> reset trim<0> trim<1> ++ trim<2> trim<3> trim<4> trim<5> trim<6> trim<7> trim<8> trim<9> ++ trim<10> trim<11> trim<12> trim<13> trim<14> trim<15> trim<16> trim<17> ++ trim<18> trim<19> trim<20> trim<21> trim<22> trim<23> trim<24> trim<25> ++ + +X_1_ _0_<0> VGND VGND VPB VPB clockp<0> sky130_fd_sc_hd__buf_2 +X_2_ _0_<1> VGND VGND VPB VPB clockp<1> sky130_fd_sc_hd__buf_2 +Xdstage<0>_id_delaybuf0 dstage<0>_id_in VGND VGND VPB VPB dstage<0>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<0>_id_delaybuf1 dstage<0>_id_ts VGND VGND VPB VPB dstage<0>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<0>_id_delayen0 dstage<0>_id_d2 trim<0> VGND VGND VPB VPB ++ dstage<0>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<0>_id_delayen1 dstage<0>_id_d0 trim<13> VGND VGND VPB VPB ++ dstage<0>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<0>_id_delayenb0 dstage<0>_id_ts trim<0> VGND VGND VPB VPB ++ dstage<0>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<0>_id_delayenb1 dstage<0>_id_ts trim<13> VGND VGND VPB VPB ++ dstage<0>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<0>_id_delayint0 dstage<0>_id_d1 VGND VGND VPB VPB dstage<0>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<10>_id_delaybuf0 dstage<10>_id_in VGND VGND VPB VPB dstage<10>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<10>_id_delaybuf1 dstage<10>_id_ts VGND VGND VPB VPB dstage<10>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<10>_id_delayen0 dstage<10>_id_d2 trim<10> VGND VGND VPB VPB ++ dstage<10>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<10>_id_delayen1 dstage<10>_id_d0 trim<23> VGND VGND VPB VPB ++ dstage<10>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<10>_id_delayenb0 dstage<10>_id_ts trim<10> VGND VGND VPB VPB ++ dstage<10>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<10>_id_delayenb1 dstage<10>_id_ts trim<23> VGND VGND VPB VPB ++ dstage<10>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<10>_id_delayint0 dstage<10>_id_d1 VGND VGND VPB VPB dstage<10>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<11>_id_delaybuf0 dstage<10>_id_out VGND VGND VPB VPB dstage<11>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<11>_id_delaybuf1 dstage<11>_id_ts VGND VGND VPB VPB dstage<11>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<11>_id_delayen0 dstage<11>_id_d2 trim<11> VGND VGND VPB VPB ++ dstage<11>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<11>_id_delayen1 dstage<11>_id_d0 trim<24> VGND VGND VPB VPB ++ dstage<11>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<11>_id_delayenb0 dstage<11>_id_ts trim<11> VGND VGND VPB VPB ++ dstage<11>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<11>_id_delayenb1 dstage<11>_id_ts trim<24> VGND VGND VPB VPB ++ dstage<11>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<11>_id_delayint0 dstage<11>_id_d1 VGND VGND VPB VPB dstage<11>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<1>_id_delaybuf0 dstage<0>_id_out VGND VGND VPB VPB dstage<1>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<1>_id_delaybuf1 dstage<1>_id_ts VGND VGND VPB VPB dstage<1>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<1>_id_delayen0 dstage<1>_id_d2 trim<1> VGND VGND VPB VPB ++ dstage<1>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<1>_id_delayen1 dstage<1>_id_d0 trim<14> VGND VGND VPB VPB ++ dstage<1>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<1>_id_delayenb0 dstage<1>_id_ts trim<1> VGND VGND VPB VPB ++ dstage<1>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<1>_id_delayenb1 dstage<1>_id_ts trim<14> VGND VGND VPB VPB ++ dstage<1>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<1>_id_delayint0 dstage<1>_id_d1 VGND VGND VPB VPB dstage<1>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<2>_id_delaybuf0 dstage<1>_id_out VGND VGND VPB VPB dstage<2>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<2>_id_delaybuf1 dstage<2>_id_ts VGND VGND VPB VPB dstage<2>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<2>_id_delayen0 dstage<2>_id_d2 trim<2> VGND VGND VPB VPB ++ dstage<2>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<2>_id_delayen1 dstage<2>_id_d0 trim<15> VGND VGND VPB VPB ++ dstage<2>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<2>_id_delayenb0 dstage<2>_id_ts trim<2> VGND VGND VPB VPB ++ dstage<2>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<2>_id_delayenb1 dstage<2>_id_ts trim<15> VGND VGND VPB VPB ++ dstage<2>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<2>_id_delayint0 dstage<2>_id_d1 VGND VGND VPB VPB dstage<2>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<3>_id_delaybuf0 dstage<2>_id_out VGND VGND VPB VPB dstage<3>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<3>_id_delaybuf1 dstage<3>_id_ts VGND VGND VPB VPB dstage<3>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<3>_id_delayen0 dstage<3>_id_d2 trim<3> VGND VGND VPB VPB ++ dstage<3>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<3>_id_delayen1 dstage<3>_id_d0 trim<16> VGND VGND VPB VPB ++ dstage<3>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<3>_id_delayenb0 dstage<3>_id_ts trim<3> VGND VGND VPB VPB ++ dstage<3>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<3>_id_delayenb1 dstage<3>_id_ts trim<16> VGND VGND VPB VPB ++ dstage<3>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<3>_id_delayint0 dstage<3>_id_d1 VGND VGND VPB VPB dstage<3>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<4>_id_delaybuf0 dstage<3>_id_out VGND VGND VPB VPB dstage<4>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<4>_id_delaybuf1 dstage<4>_id_ts VGND VGND VPB VPB dstage<4>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<4>_id_delayen0 dstage<4>_id_d2 trim<4> VGND VGND VPB VPB ++ dstage<4>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<4>_id_delayen1 dstage<4>_id_d0 trim<17> VGND VGND VPB VPB ++ dstage<4>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<4>_id_delayenb0 dstage<4>_id_ts trim<4> VGND VGND VPB VPB ++ dstage<4>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<4>_id_delayenb1 dstage<4>_id_ts trim<17> VGND VGND VPB VPB ++ dstage<4>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<4>_id_delayint0 dstage<4>_id_d1 VGND VGND VPB VPB dstage<4>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<5>_id_delaybuf0 dstage<4>_id_out VGND VGND VPB VPB dstage<5>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<5>_id_delaybuf1 dstage<5>_id_ts VGND VGND VPB VPB dstage<5>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<5>_id_delayen0 dstage<5>_id_d2 trim<5> VGND VGND VPB VPB ++ dstage<5>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<5>_id_delayen1 dstage<5>_id_d0 trim<18> VGND VGND VPB VPB ++ dstage<5>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<5>_id_delayenb0 dstage<5>_id_ts trim<5> VGND VGND VPB VPB ++ dstage<5>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<5>_id_delayenb1 dstage<5>_id_ts trim<18> VGND VGND VPB VPB ++ dstage<5>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<5>_id_delayint0 dstage<5>_id_d1 VGND VGND VPB VPB dstage<5>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<6>_id_delaybuf0 dstage<5>_id_out VGND VGND VPB VPB dstage<6>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<6>_id_delaybuf1 dstage<6>_id_ts VGND VGND VPB VPB dstage<6>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<6>_id_delayen0 dstage<6>_id_d2 trim<6> VGND VGND VPB VPB ++ dstage<6>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<6>_id_delayen1 dstage<6>_id_d0 trim<19> VGND VGND VPB VPB ++ dstage<6>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<6>_id_delayenb0 dstage<6>_id_ts trim<6> VGND VGND VPB VPB ++ dstage<6>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<6>_id_delayenb1 dstage<6>_id_ts trim<19> VGND VGND VPB VPB ++ dstage<6>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<6>_id_delayint0 dstage<6>_id_d1 VGND VGND VPB VPB dstage<6>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<7>_id_delaybuf0 dstage<6>_id_out VGND VGND VPB VPB dstage<7>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<7>_id_delaybuf1 dstage<7>_id_ts VGND VGND VPB VPB dstage<7>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<7>_id_delayen0 dstage<7>_id_d2 trim<7> VGND VGND VPB VPB ++ dstage<7>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<7>_id_delayen1 dstage<7>_id_d0 trim<20> VGND VGND VPB VPB ++ dstage<7>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<7>_id_delayenb0 dstage<7>_id_ts trim<7> VGND VGND VPB VPB ++ dstage<7>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<7>_id_delayenb1 dstage<7>_id_ts trim<20> VGND VGND VPB VPB ++ dstage<7>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<7>_id_delayint0 dstage<7>_id_d1 VGND VGND VPB VPB dstage<7>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<8>_id_delaybuf0 dstage<7>_id_out VGND VGND VPB VPB dstage<8>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<8>_id_delaybuf1 dstage<8>_id_ts VGND VGND VPB VPB dstage<8>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<8>_id_delayen0 dstage<8>_id_d2 trim<8> VGND VGND VPB VPB ++ dstage<8>_id_out ++ sky130_fd_sc_hd__einvp_2 +Xdstage<8>_id_delayen1 dstage<8>_id_d0 trim<21> VGND VGND VPB VPB ++ dstage<8>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<8>_id_delayenb0 dstage<8>_id_ts trim<8> VGND VGND VPB VPB ++ dstage<8>_id_out ++ sky130_fd_sc_hd__einvn_8 +Xdstage<8>_id_delayenb1 dstage<8>_id_ts trim<21> VGND VGND VPB VPB ++ dstage<8>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<8>_id_delayint0 dstage<8>_id_d1 VGND VGND VPB VPB dstage<8>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xdstage<9>_id_delaybuf0 dstage<8>_id_out VGND VGND VPB VPB dstage<9>_id_ts sky130_fd_sc_hd__clkbuf_2 +Xdstage<9>_id_delaybuf1 dstage<9>_id_ts VGND VGND VPB VPB dstage<9>_id_d0 sky130_fd_sc_hd__clkbuf_1 +Xdstage<9>_id_delayen0 dstage<9>_id_d2 trim<9> VGND VGND VPB VPB ++ dstage<10>_id_in ++ sky130_fd_sc_hd__einvp_2 +Xdstage<9>_id_delayen1 dstage<9>_id_d0 trim<22> VGND VGND VPB VPB ++ dstage<9>_id_d1 ++ sky130_fd_sc_hd__einvp_2 +Xdstage<9>_id_delayenb0 dstage<9>_id_ts trim<9> VGND VGND VPB VPB ++ dstage<10>_id_in ++ sky130_fd_sc_hd__einvn_8 +Xdstage<9>_id_delayenb1 dstage<9>_id_ts trim<22> VGND VGND VPB VPB ++ dstage<9>_id_d1 ++ sky130_fd_sc_hd__einvn_4 +Xdstage<9>_id_delayint0 dstage<9>_id_d1 VGND VGND VPB VPB dstage<9>_id_d2 sky130_fd_sc_hd__clkinv_1 +Xibufp00 dstage<0>_id_in VGND VGND VPB VPB c<0> sky130_fd_sc_hd__clkinv_2 +Xibufp01 c<0> VGND VGND VPB VPB _0_<0> sky130_fd_sc_hd__clkinv_8 +Xibufp10 dstage<5>_id_out VGND VGND VPB VPB c<1> sky130_fd_sc_hd__clkinv_2 +Xibufp11 c<1> VGND VGND VPB VPB _0_<1> sky130_fd_sc_hd__clkinv_8 +Xiss_const1 VGND VGND VPB VPB iss_one _noconnect_1_ sky130_fd_sc_hd__conb_1 +Xiss_ctrlen0 reset trim<12> VGND VGND VPB VPB ++ iss_ctrl0 ++ sky130_fd_sc_hd__or2_2 +Xiss_delaybuf0 dstage<11>_id_out VGND VGND VPB VPB iss_d0 sky130_fd_sc_hd__clkbuf_1 +Xiss_delayen0 iss_d2 trim<12> VGND VGND VPB VPB ++ dstage<0>_id_in ++ sky130_fd_sc_hd__einvp_2 +Xiss_delayen1 iss_d0 trim<25> VGND VGND VPB VPB ++ iss_d1 ++ sky130_fd_sc_hd__einvp_2 +Xiss_delayenb0 dstage<11>_id_out iss_ctrl0 VGND VGND VPB VPB ++ dstage<0>_id_in ++ sky130_fd_sc_hd__einvn_8 +Xiss_delayenb1 dstage<11>_id_out trim<25> VGND VGND VPB VPB ++ iss_d1 ++ sky130_fd_sc_hd__einvn_4 +Xiss_delayint0 iss_d1 VGND VGND VPB VPB iss_d2 sky130_fd_sc_hd__clkinv_1 +Xiss_reseten0 iss_one reset VGND VGND VPB VPB ++ dstage<0>_id_in ++ sky130_fd_sc_hd__einvp_1 +Xantenna_0 reset VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<25> trim<25> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<24> trim<24> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<23> trim<23> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<22> trim<22> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<21> trim<21> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<20> trim<20> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<19> trim<19> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<18> trim<18> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<17> trim<17> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<16> trim<16> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<15> trim<15> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<14> trim<14> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<13> trim<13> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<12> trim<12> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<11> trim<11> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<10> trim<10> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<9> trim<9> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<8> trim<8> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<7> trim<7> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<6> trim<6> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<5> trim<5> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<4> trim<4> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<3> trim<3> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<2> trim<2> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<1> trim<1> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1<0> trim<0> VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 + +.ends +.end
diff --git a/ngspice/digital_pll/digital_pll/ring_osc2x13.spice.bak b/ngspice/digital_pll/digital_pll/ring_osc2x13.spice.bak new file mode 100644 index 0000000..c49b71c --- /dev/null +++ b/ngspice/digital_pll/digital_pll/ring_osc2x13.spice.bak
@@ -0,0 +1,264 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* SPICE netlist created from verilog structural netlist module ring_osc2x13 by vlog2Spice (qflow) +* Warning: This file contains [] array delimiters in net names. +* Note: Library sky130_fd_sc_hd.spice has been removed; reference library as an +* include file from the testbench instead. + +.subckt ring_osc2x13 VPB VGND clockp[0] clockp[1] reset trim[0] trim[1] ++ trim[2] trim[3] trim[4] trim[5] trim[6] trim[7] trim[8] trim[9] ++ trim[10] trim[11] trim[12] trim[13] trim[14] trim[15] trim[16] trim[17] ++ trim[18] trim[19] trim[20] trim[21] trim[22] trim[23] trim[24] trim[25] ++ + +X_1_ _0_[0] VGND VGND VPB VPB clockp[0] sky130_fd_sc_hd__buf_2 +X_2_ _0_[1] VGND VGND VPB VPB clockp[1] sky130_fd_sc_hd__buf_2 +X\dstage[0].id.delaybuf0 \dstage[0].id.in\ VGND VGND VPB VPB \dstage[0].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[0].id.delaybuf1 \dstage[0].id.ts\ VGND VGND VPB VPB \dstage[0].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[0].id.delayen0 \dstage[0].id.d2\ trim[0] VGND VGND VPB VPB ++ \dstage[0].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[0].id.delayen1 \dstage[0].id.d0\ trim[13] VGND VGND VPB VPB ++ \dstage[0].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[0].id.delayenb0 \dstage[0].id.ts\ trim[0] VGND VGND VPB VPB ++ \dstage[0].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[0].id.delayenb1 \dstage[0].id.ts\ trim[13] VGND VGND VPB VPB ++ \dstage[0].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[0].id.delayint0 \dstage[0].id.d1\ VGND VGND VPB VPB \dstage[0].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[10].id.delaybuf0 \dstage[10].id.in\ VGND VGND VPB VPB \dstage[10].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[10].id.delaybuf1 \dstage[10].id.ts\ VGND VGND VPB VPB \dstage[10].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[10].id.delayen0 \dstage[10].id.d2\ trim[10] VGND VGND VPB VPB ++ \dstage[10].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[10].id.delayen1 \dstage[10].id.d0\ trim[23] VGND VGND VPB VPB ++ \dstage[10].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[10].id.delayenb0 \dstage[10].id.ts\ trim[10] VGND VGND VPB VPB ++ \dstage[10].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[10].id.delayenb1 \dstage[10].id.ts\ trim[23] VGND VGND VPB VPB ++ \dstage[10].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[10].id.delayint0 \dstage[10].id.d1\ VGND VGND VPB VPB \dstage[10].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[11].id.delaybuf0 \dstage[10].id.out\ VGND VGND VPB VPB \dstage[11].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[11].id.delaybuf1 \dstage[11].id.ts\ VGND VGND VPB VPB \dstage[11].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[11].id.delayen0 \dstage[11].id.d2\ trim[11] VGND VGND VPB VPB ++ \dstage[11].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[11].id.delayen1 \dstage[11].id.d0\ trim[24] VGND VGND VPB VPB ++ \dstage[11].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[11].id.delayenb0 \dstage[11].id.ts\ trim[11] VGND VGND VPB VPB ++ \dstage[11].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[11].id.delayenb1 \dstage[11].id.ts\ trim[24] VGND VGND VPB VPB ++ \dstage[11].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[11].id.delayint0 \dstage[11].id.d1\ VGND VGND VPB VPB \dstage[11].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[1].id.delaybuf0 \dstage[0].id.out\ VGND VGND VPB VPB \dstage[1].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[1].id.delaybuf1 \dstage[1].id.ts\ VGND VGND VPB VPB \dstage[1].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[1].id.delayen0 \dstage[1].id.d2\ trim[1] VGND VGND VPB VPB ++ \dstage[1].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[1].id.delayen1 \dstage[1].id.d0\ trim[14] VGND VGND VPB VPB ++ \dstage[1].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[1].id.delayenb0 \dstage[1].id.ts\ trim[1] VGND VGND VPB VPB ++ \dstage[1].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[1].id.delayenb1 \dstage[1].id.ts\ trim[14] VGND VGND VPB VPB ++ \dstage[1].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[1].id.delayint0 \dstage[1].id.d1\ VGND VGND VPB VPB \dstage[1].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[2].id.delaybuf0 \dstage[1].id.out\ VGND VGND VPB VPB \dstage[2].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[2].id.delaybuf1 \dstage[2].id.ts\ VGND VGND VPB VPB \dstage[2].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[2].id.delayen0 \dstage[2].id.d2\ trim[2] VGND VGND VPB VPB ++ \dstage[2].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[2].id.delayen1 \dstage[2].id.d0\ trim[15] VGND VGND VPB VPB ++ \dstage[2].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[2].id.delayenb0 \dstage[2].id.ts\ trim[2] VGND VGND VPB VPB ++ \dstage[2].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[2].id.delayenb1 \dstage[2].id.ts\ trim[15] VGND VGND VPB VPB ++ \dstage[2].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[2].id.delayint0 \dstage[2].id.d1\ VGND VGND VPB VPB \dstage[2].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[3].id.delaybuf0 \dstage[2].id.out\ VGND VGND VPB VPB \dstage[3].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[3].id.delaybuf1 \dstage[3].id.ts\ VGND VGND VPB VPB \dstage[3].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[3].id.delayen0 \dstage[3].id.d2\ trim[3] VGND VGND VPB VPB ++ \dstage[3].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[3].id.delayen1 \dstage[3].id.d0\ trim[16] VGND VGND VPB VPB ++ \dstage[3].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[3].id.delayenb0 \dstage[3].id.ts\ trim[3] VGND VGND VPB VPB ++ \dstage[3].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[3].id.delayenb1 \dstage[3].id.ts\ trim[16] VGND VGND VPB VPB ++ \dstage[3].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[3].id.delayint0 \dstage[3].id.d1\ VGND VGND VPB VPB \dstage[3].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[4].id.delaybuf0 \dstage[3].id.out\ VGND VGND VPB VPB \dstage[4].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[4].id.delaybuf1 \dstage[4].id.ts\ VGND VGND VPB VPB \dstage[4].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[4].id.delayen0 \dstage[4].id.d2\ trim[4] VGND VGND VPB VPB ++ \dstage[4].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[4].id.delayen1 \dstage[4].id.d0\ trim[17] VGND VGND VPB VPB ++ \dstage[4].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[4].id.delayenb0 \dstage[4].id.ts\ trim[4] VGND VGND VPB VPB ++ \dstage[4].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[4].id.delayenb1 \dstage[4].id.ts\ trim[17] VGND VGND VPB VPB ++ \dstage[4].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[4].id.delayint0 \dstage[4].id.d1\ VGND VGND VPB VPB \dstage[4].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[5].id.delaybuf0 \dstage[4].id.out\ VGND VGND VPB VPB \dstage[5].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[5].id.delaybuf1 \dstage[5].id.ts\ VGND VGND VPB VPB \dstage[5].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[5].id.delayen0 \dstage[5].id.d2\ trim[5] VGND VGND VPB VPB ++ \dstage[5].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[5].id.delayen1 \dstage[5].id.d0\ trim[18] VGND VGND VPB VPB ++ \dstage[5].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[5].id.delayenb0 \dstage[5].id.ts\ trim[5] VGND VGND VPB VPB ++ \dstage[5].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[5].id.delayenb1 \dstage[5].id.ts\ trim[18] VGND VGND VPB VPB ++ \dstage[5].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[5].id.delayint0 \dstage[5].id.d1\ VGND VGND VPB VPB \dstage[5].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[6].id.delaybuf0 \dstage[5].id.out\ VGND VGND VPB VPB \dstage[6].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[6].id.delaybuf1 \dstage[6].id.ts\ VGND VGND VPB VPB \dstage[6].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[6].id.delayen0 \dstage[6].id.d2\ trim[6] VGND VGND VPB VPB ++ \dstage[6].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[6].id.delayen1 \dstage[6].id.d0\ trim[19] VGND VGND VPB VPB ++ \dstage[6].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[6].id.delayenb0 \dstage[6].id.ts\ trim[6] VGND VGND VPB VPB ++ \dstage[6].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[6].id.delayenb1 \dstage[6].id.ts\ trim[19] VGND VGND VPB VPB ++ \dstage[6].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[6].id.delayint0 \dstage[6].id.d1\ VGND VGND VPB VPB \dstage[6].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[7].id.delaybuf0 \dstage[6].id.out\ VGND VGND VPB VPB \dstage[7].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[7].id.delaybuf1 \dstage[7].id.ts\ VGND VGND VPB VPB \dstage[7].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[7].id.delayen0 \dstage[7].id.d2\ trim[7] VGND VGND VPB VPB ++ \dstage[7].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[7].id.delayen1 \dstage[7].id.d0\ trim[20] VGND VGND VPB VPB ++ \dstage[7].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[7].id.delayenb0 \dstage[7].id.ts\ trim[7] VGND VGND VPB VPB ++ \dstage[7].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[7].id.delayenb1 \dstage[7].id.ts\ trim[20] VGND VGND VPB VPB ++ \dstage[7].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[7].id.delayint0 \dstage[7].id.d1\ VGND VGND VPB VPB \dstage[7].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[8].id.delaybuf0 \dstage[7].id.out\ VGND VGND VPB VPB \dstage[8].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[8].id.delaybuf1 \dstage[8].id.ts\ VGND VGND VPB VPB \dstage[8].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[8].id.delayen0 \dstage[8].id.d2\ trim[8] VGND VGND VPB VPB ++ \dstage[8].id.out\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[8].id.delayen1 \dstage[8].id.d0\ trim[21] VGND VGND VPB VPB ++ \dstage[8].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[8].id.delayenb0 \dstage[8].id.ts\ trim[8] VGND VGND VPB VPB ++ \dstage[8].id.out\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[8].id.delayenb1 \dstage[8].id.ts\ trim[21] VGND VGND VPB VPB ++ \dstage[8].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[8].id.delayint0 \dstage[8].id.d1\ VGND VGND VPB VPB \dstage[8].id.d2\ sky130_fd_sc_hd__clkinv_1 +X\dstage[9].id.delaybuf0 \dstage[8].id.out\ VGND VGND VPB VPB \dstage[9].id.ts\ sky130_fd_sc_hd__clkbuf_2 +X\dstage[9].id.delaybuf1 \dstage[9].id.ts\ VGND VGND VPB VPB \dstage[9].id.d0\ sky130_fd_sc_hd__clkbuf_1 +X\dstage[9].id.delayen0 \dstage[9].id.d2\ trim[9] VGND VGND VPB VPB ++ \dstage[10].id.in\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[9].id.delayen1 \dstage[9].id.d0\ trim[22] VGND VGND VPB VPB ++ \dstage[9].id.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\dstage[9].id.delayenb0 \dstage[9].id.ts\ trim[9] VGND VGND VPB VPB ++ \dstage[10].id.in\ ++ sky130_fd_sc_hd__einvn_8 +X\dstage[9].id.delayenb1 \dstage[9].id.ts\ trim[22] VGND VGND VPB VPB ++ \dstage[9].id.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\dstage[9].id.delayint0 \dstage[9].id.d1\ VGND VGND VPB VPB \dstage[9].id.d2\ sky130_fd_sc_hd__clkinv_1 +Xibufp00 \dstage[0].id.in\ VGND VGND VPB VPB c[0] sky130_fd_sc_hd__clkinv_2 +Xibufp01 c[0] VGND VGND VPB VPB _0_[0] sky130_fd_sc_hd__clkinv_8 +Xibufp10 \dstage[5].id.out\ VGND VGND VPB VPB c[1] sky130_fd_sc_hd__clkinv_2 +Xibufp11 c[1] VGND VGND VPB VPB _0_[1] sky130_fd_sc_hd__clkinv_8 +X\iss.const1 VGND VGND VPB VPB \iss.one\ _noconnect_1_ sky130_fd_sc_hd__conb_1 +X\iss.ctrlen0 reset trim[12] VGND VGND VPB VPB ++ \iss.ctrl0\ ++ sky130_fd_sc_hd__or2_2 +X\iss.delaybuf0 \dstage[11].id.out\ VGND VGND VPB VPB \iss.d0\ sky130_fd_sc_hd__clkbuf_1 +X\iss.delayen0 \iss.d2\ trim[12] VGND VGND VPB VPB ++ \dstage[0].id.in\ ++ sky130_fd_sc_hd__einvp_2 +X\iss.delayen1 \iss.d0\ trim[25] VGND VGND VPB VPB ++ \iss.d1\ ++ sky130_fd_sc_hd__einvp_2 +X\iss.delayenb0 \dstage[11].id.out\ \iss.ctrl0\ VGND VGND VPB VPB ++ \dstage[0].id.in\ ++ sky130_fd_sc_hd__einvn_8 +X\iss.delayenb1 \dstage[11].id.out\ trim[25] VGND VGND VPB VPB ++ \iss.d1\ ++ sky130_fd_sc_hd__einvn_4 +X\iss.delayint0 \iss.d1\ VGND VGND VPB VPB \iss.d2\ sky130_fd_sc_hd__clkinv_1 +X\iss.reseten0 \iss.one\ reset VGND VGND VPB VPB ++ \dstage[0].id.in\ ++ sky130_fd_sc_hd__einvp_1 +Xantenna_0 reset VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[25] trim[25] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[24] trim[24] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[23] trim[23] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[22] trim[22] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[21] trim[21] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[20] trim[20] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[19] trim[19] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[18] trim[18] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[17] trim[17] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[16] trim[16] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[15] trim[15] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[14] trim[14] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[13] trim[13] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[12] trim[12] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[11] trim[11] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[10] trim[10] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[9] trim[9] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[8] trim[8] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[7] trim[7] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[6] trim[6] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[5] trim[5] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[4] trim[4] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[3] trim[3] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[2] trim[2] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[1] trim[1] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 +Xantenna_1[0] trim[0] VGND VGND VPB VPB sky130_fd_sc_hd__diode_2 + +.ends +.end
diff --git a/ngspice/digital_pll/digital_pll/ring_osc2x13_tb.spice b/ngspice/digital_pll/digital_pll/ring_osc2x13_tb.spice new file mode 100644 index 0000000..b2c3cae --- /dev/null +++ b/ngspice/digital_pll/digital_pll/ring_osc2x13_tb.spice
@@ -0,0 +1,58 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Ring oscillator testbench---simple check of ring oscillator +* at several trim levels + +.lib "/home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice" tt + +.include "/home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice" + +.include "ring_osc2x13.spice" + +.option TEMP=27 +* .option RELTOL=1.0E-1 +* .option RSHUNT=1.0E20 + +* Instantiate the ring oscillator +* Tie trims together in four sets + +X0 vdd vss clockp0 clockp1 reset trim0 trim1 trim0 trim1 trim0 trim1 trim0 ++ trim1 trim0 trim1 trim0 trim1 trim0 trim3 trim2 trim3 trim2 trim3 trim2 ++ trim3 trim2 trim3 trim2 trim3 trim2 trim3 ring_osc2x13 + +* Power supply (note that all logic is 1.8V here) + +V0 vdd vss PWL(0n 0.0 30n 1.8) +V1 vss 0 0.0 + +* Trim values (connect resistors to power or ground) +* divider value = 12 + +V2 trim0 gnd PULSE(0.0 1.8 200n 2n 2n 1u 2u) +V3 trim1 gnd PULSE(0.0 1.8 400n 2n 2n 1u 2u) +V4 trim2 gnd PULSE(0.0 1.8 600n 2n 2n 1u 2u) +V5 trim3 gnd PULSE(0.0 1.8 800n 2n 2n 1u 2u) + +* Reset +V6 reset gnd PWL(0n 1.8 48n 1.8 50n 0.0) + +* Transient analysis +.control +tran 100p 1u +plot V(clockp0) V(clockp1) +.endc +.end
diff --git a/ngspice/digital_pll/digital_pll/ring_osc2x13_tb2.spice b/ngspice/digital_pll/digital_pll/ring_osc2x13_tb2.spice new file mode 100644 index 0000000..93406af --- /dev/null +++ b/ngspice/digital_pll/digital_pll/ring_osc2x13_tb2.spice
@@ -0,0 +1,80 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Ring oscillator testbench---simple check of ring oscillator +* at several trim levels + +.lib "/home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice" tt + +.include "/home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice" + +.include "ring_osc2x13.spice" + +.option TEMP=27 +* .option RELTOL=1.0E-1 +* .option RSHUNT=1.0E20 + +* Instantiate the ring oscillator +* Tie trims together in four sets + +X0 vdd vss clockp0 clockp1 reset trim00 trim01 trim02 trim03 trim04 trim05 trim06 ++ trim07 trim08 trim09 trim10 trim11 trim12 trim13 trim14 trim15 trim16 trim17 ++ trim18 trim19 trim20 trim21 trim22 trim23 trim24 trim25 ring_osc2x13 + +* Power supply (note that all logic is 1.8V here) + +V00 vdd vss PWL(0n 0.0 30n 1.8) +V01 vss 0 0.0 + +* Trim values (connect resistors to power or ground) +* divider value = 12 + +V02 trim00 gnd PULSE(0.0 1.8 40n 2n 2n 1u 2u) +V03 trim01 gnd PULSE(0.0 1.8 80n 2n 2n 1u 2u) +V04 trim02 gnd PULSE(0.0 1.8 120n 2n 2n 1u 2u) +V05 trim03 gnd PULSE(0.0 1.8 160n 2n 2n 1u 2u) +V06 trim04 gnd PULSE(0.0 1.8 200n 2n 2n 1u 2u) +V07 trim05 gnd PULSE(0.0 1.8 240n 2n 2n 1u 2u) +V08 trim06 gnd PULSE(0.0 1.8 280n 2n 2n 1u 2u) +V09 trim07 gnd PULSE(0.0 1.8 320n 2n 2n 1u 2u) +V10 trim08 gnd PULSE(0.0 1.8 360n 2n 2n 1u 2u) +V11 trim09 gnd PULSE(0.0 1.8 400n 2n 2n 1u 2u) +V12 trim10 gnd PULSE(0.0 1.8 440n 2n 2n 1u 2u) +V13 trim11 gnd PULSE(0.0 1.8 480n 2n 2n 1u 2u) +V14 trim12 gnd PULSE(0.0 1.8 520n 2n 2n 1u 2u) +V15 trim13 gnd PULSE(0.0 1.8 560n 2n 2n 1u 2u) +V16 trim14 gnd PULSE(0.0 1.8 600n 2n 2n 1u 2u) +V17 trim15 gnd PULSE(0.0 1.8 640n 2n 2n 1u 2u) +V18 trim16 gnd PULSE(0.0 1.8 680n 2n 2n 1u 2u) +V19 trim17 gnd PULSE(0.0 1.8 720n 2n 2n 1u 2u) +V20 trim18 gnd PULSE(0.0 1.8 760n 2n 2n 1u 2u) +V21 trim19 gnd PULSE(0.0 1.8 800n 2n 2n 1u 2u) +V22 trim20 gnd PULSE(0.0 1.8 840n 2n 2n 1u 2u) +V23 trim21 gnd PULSE(0.0 1.8 880n 2n 2n 1u 2u) +V24 trim22 gnd PULSE(0.0 1.8 920n 2n 2n 1u 2u) +V25 trim23 gnd PULSE(0.0 1.8 960n 2n 2n 1u 2u) +V26 trim24 gnd PULSE(0.0 1.8 800n 2n 2n 1u 2u) +V27 trim25 gnd PULSE(0.0 1.8 840n 2n 2n 1u 2u) + +* Reset +V6 reset gnd PWL(0n 1.8 8n 1.8 10n 0.0) + +* Transient analysis +.control +tran 100p 1u +plot V(clockp0) V(clockp1) +.endc +.end
diff --git a/ngspice/simple_por/simple_por/current_test.spice b/ngspice/simple_por/simple_por/current_test.spice new file mode 100644 index 0000000..da74e24 --- /dev/null +++ b/ngspice/simple_por/simple_por/current_test.spice
@@ -0,0 +1,85 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Simple POR circuit for Caravel current mirror test +*------------------------------------------------------------------- + +.lib /home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice tt + +* Note: 20 resistors of length 25um connected in series +Xres1 vdda vin vss sky130_fd_pr__res_xhigh_po_0p69 l=500 +Xres2 vin vss vss sky130_fd_pr__res_xhigh_po_0p69 l=149 + +* voltage sources at 0V for measuring current in each branch + +Vm1 vssm1 vss DC=0 +Vm2 vdda vddm2 DC=0 +Vm3 vdda vddm3 DC=0 +Vm4 vssm4 vss DC=0 +Vm5 vssm5 vss DC=0 +Vm6 vdda vddm6 DC=0 +Vm7 vdda vddm7 DC=0 + +* D G S B +Xm1 casc1 vin vssm1 vss sky130_fd_pr__nfet_g5v0d10v5 w=2 l=0.8 m=1 +Xc1 mir1 casc1 casc1 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=1 +Xm2 mir1 mir1 vddm2 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=8 +Xm3 mir2 mir1 vddm3 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=1 +Xc2 casc2 casc1 mir2 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=1 +Xm4 casc2 casc2 vssm4 vss sky130_fd_pr__nfet_g5v0d10v5 w=2 l=0.8 m=7 +Xm5 casc3 casc2 vssm5 vss sky130_fd_pr__nfet_g5v0d10v5 w=2 l=0.8 m=1 +Xc3 mir3 casc3 casc3 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=1 +Xm6 mir3 mir3 vddm6 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=7 +Xm7 mir4 mir3 vddm7 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=1 +Xc4 vcap casc3 mir4 vdda sky130_fd_pr__pfet_g5v0d10v5 w=2 l=0.8 m=1 + +* Check branch currents in each mirror branch. +* 1st branch should be 240nA +* 2nd branch should be 30nA +* 3rd branch should be 4.3nA +* 4th branch should be 612pA +* +* Result: vin sits at 0.7590 (close to 0.7575 target) +* I(Vm1/2) = 202.80 nA +* I(Vm3/4) = 26.10 nA (should be /8) actually /7.77 +* I(Vm5/6) = 4.58 nA (should be /7) actually /5.70 +* I(Vm7) = 0.67 pA (should be /7) actually /6.80 + +*---------------------------- +* Testbench circuit +*---------------------------- +Vpwr vdda vss DC=3.3 +Rgnd vss 0 0.01 +Rload vcap vss 1MEG +*---------------------------- + +*---------------------------- +* Testbench control +*---------------------------- +.control +op +print V(vin) +print I(Vm1) +print I(Vm2) +print I(Vm3) +print I(Vm4) +print I(Vm5) +print I(Vm6) +print I(Vm7) +.endc + +.end +
diff --git a/ngspice/simple_por/simple_por/simple_por.spice b/ngspice/simple_por/simple_por/simple_por.spice new file mode 100644 index 0000000..2aa5265 --- /dev/null +++ b/ngspice/simple_por/simple_por/simple_por.spice
@@ -0,0 +1,229 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* NGSPICE file created from simple_por.ext - technology: sky130A + +.subckt sky130_fd_pr__cap_mim_m3_2_W5U4AW VSUBS m4_n3179_n3100# c2_n3079_n3000# +X0 c2_n3079_n3000# m4_n3179_n3100# sky130_fd_pr__cap_mim_m3_2 l=3e+07u w=3e+07u +.ends + +.subckt sky130_fd_sc_hvl__buf_8 A VGND VNB VPB VPWR X +X0 VPWR A a_45_443# VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X1 VGND a_45_443# X VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X2 VPWR a_45_443# X VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X3 VGND a_45_443# X VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X4 VGND a_45_443# X VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X5 a_45_443# A VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X6 X a_45_443# VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X7 X a_45_443# VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X8 VGND A a_45_443# VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X9 VPWR a_45_443# X VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X10 X a_45_443# VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X11 X a_45_443# VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X12 VPWR a_45_443# X VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X13 VPWR a_45_443# X VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X14 VPWR A a_45_443# VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X15 a_45_443# A VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X16 VGND A a_45_443# VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X17 X a_45_443# VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X18 X a_45_443# VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X19 VGND a_45_443# X VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X20 X a_45_443# VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X21 X a_45_443# VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +.ends + +.subckt sky130_fd_pr__pfet_g5v0d10v5_ZEUEFZ VSUBS a_n465_n200# a_n247_n200# a_n29_n200# ++ a_843_n200# w_n1101_n497# a_n843_n297# a_625_n200# a_683_n297# a_n625_n297# a_407_n200# ++ a_465_n297# a_n407_n297# a_247_n297# a_n901_n200# a_189_n200# a_29_n297# a_n189_n297# ++ a_n683_n200# +X0 a_407_n200# a_247_n297# a_189_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X1 a_843_n200# a_683_n297# a_625_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X2 a_n465_n200# a_n625_n297# a_n683_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X3 a_189_n200# a_29_n297# a_n29_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X4 a_625_n200# a_465_n297# a_407_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X5 a_n247_n200# a_n407_n297# a_n465_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X6 a_n683_n200# a_n843_n297# a_n901_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X7 a_n29_n200# a_n189_n297# a_n247_n200# w_n1101_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_pr__nfet_g5v0d10v5_TGFUGS VSUBS a_n80_n288# a_n574_n200# a_n356_n200# ++ a_n138_n200# a_n734_n288# a_574_n288# a_n516_n288# a_356_n288# a_80_n200# a_n298_n288# ++ a_138_n288# w_n962_n458# a_734_n200# a_516_n200# a_298_n200# a_n792_n200# +X0 a_516_n200# a_356_n288# a_298_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +X1 a_n574_n200# a_n734_n288# a_n792_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +X2 a_298_n200# a_138_n288# a_80_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +X3 a_80_n200# a_n80_n288# a_n138_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +X4 a_734_n200# a_574_n288# a_516_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +X5 a_n356_n200# a_n516_n288# a_n574_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +X6 a_n138_n200# a_n298_n288# a_n356_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_pr__res_xhigh_po_0p69_S5N9F3 VSUBS a_n2578_n2932# a_5142_2500# a_n1034_n2932# ++ a_n262_2500# a_1668_2500# a_n262_n2932# a_n3736_2500# a_3984_n2932# a_n2192_2500# ++ a_3984_2500# a_2440_n2932# a_2440_2500# a_4370_n2932# a_3598_2500# a_2054_2500# ++ a_n4508_n2932# a_510_2500# a_n4122_2500# a_n2964_n2932# a_124_2500# a_n4894_n2932# ++ a_1282_n2932# a_124_n2932# a_n1420_n2932# a_4370_2500# a_n3350_n2932# a_n648_n2932# ++ a_n648_2500# a_n5280_n2932# a_n1420_2500# a_n2964_2500# a_n2578_2500# a_n1034_2500# ++ a_2826_n2932# a_n2192_n2932# a_2826_2500# a_4756_n2932# w_n5446_n3098# a_1282_2500# ++ a_3212_n2932# a_n4894_2500# a_n3350_2500# a_n4508_2500# a_5142_n2932# a_896_2500# ++ a_510_n2932# a_1668_n2932# a_n1806_n2932# a_4756_2500# a_n3736_n2932# a_3598_n2932# ++ a_3212_2500# a_2054_n2932# a_896_n2932# a_n5280_2500# a_n4122_n2932# a_n1806_2500# +X0 a_n3350_n2932# a_n3350_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X1 a_n4508_n2932# a_n4508_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X2 a_n2578_n2932# a_n2578_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X3 a_n1420_n2932# a_n1420_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X4 a_n4894_n2932# a_n4894_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X5 a_n3736_n2932# a_n3736_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X6 a_3598_n2932# a_3598_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X7 a_124_n2932# a_124_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X8 a_4756_n2932# a_4756_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X9 a_n2964_n2932# a_n2964_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X10 a_1668_n2932# a_1668_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X11 a_n1806_n2932# a_n1806_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X12 a_n648_n2932# a_n648_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X13 a_3984_n2932# a_3984_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X14 a_2826_n2932# a_2826_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X15 a_510_n2932# a_510_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X16 a_n4122_n2932# a_n4122_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X17 a_n2192_n2932# a_n2192_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X18 a_5142_n2932# a_5142_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X19 a_n1034_n2932# a_n1034_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X20 a_2054_n2932# a_2054_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X21 a_4370_n2932# a_4370_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X22 a_3212_n2932# a_3212_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X23 a_1282_n2932# a_1282_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X24 a_n262_n2932# a_n262_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X25 a_n5280_n2932# a_n5280_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X26 a_2440_n2932# a_2440_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +X27 a_896_n2932# a_896_2500# VSUBS sky130_fd_pr__res_xhigh_po_0p69 l=2.5e+07u +.ends + +.subckt sky130_fd_pr__pfet_g5v0d10v5_3YBPVB VSUBS a_n138_n200# w_n338_n497# a_80_n200# ++ a_n80_n297# +X0 a_80_n200# a_n80_n297# a_n138_n200# w_n338_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_sc_hvl__schmittbuf_1 A VGND VNB VPB VPWR X +X0 a_64_207# VPWR VPB sky130_fd_pr__res_generic_pd__hv w=290000u l=3.11e+06u +X1 a_231_463# A a_117_181# VPB sky130_fd_pr__pfet_g5v0d10v5 w=750000u l=500000u +X2 a_217_207# A a_117_181# VNB sky130_fd_pr__nfet_g5v0d10v5 w=420000u l=500000u +X3 VPWR A a_231_463# VPB sky130_fd_pr__pfet_g5v0d10v5 w=750000u l=500000u +X4 a_217_207# a_117_181# a_64_207# VNB sky130_fd_pr__nfet_g5v0d10v5 w=420000u l=500000u +X5 X a_117_181# VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X6 a_78_463# VGND VNB sky130_fd_pr__res_generic_nd__hv w=290000u l=1.355e+06u +X7 X a_117_181# VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X8 VGND A a_217_207# VNB sky130_fd_pr__nfet_g5v0d10v5 w=420000u l=500000u +X9 a_231_463# a_117_181# a_78_463# VPB sky130_fd_pr__pfet_g5v0d10v5 w=750000u l=500000u +.ends + +.subckt sky130_fd_pr__pfet_g5v0d10v5_YUHPXE VSUBS a_n138_n200# w_n338_n497# a_80_n200# ++ a_n80_n297# +X0 a_80_n200# a_n80_n297# a_n138_n200# w_n338_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_pr__nfet_g5v0d10v5_PKVMTM VSUBS a_n80_n288# a_n138_n200# a_80_n200# ++ w_n308_n458# +X0 a_80_n200# a_n80_n288# a_n138_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_pr__nfet_g5v0d10v5_ZK8HQC VSUBS a_n80_n288# a_n138_n200# a_80_n200# ++ w_n308_n458# +X0 a_80_n200# a_n80_n288# a_n138_n200# VSUBS sky130_fd_pr__nfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_pr__cap_mim_m3_1_WRT4AW VSUBS m3_n3136_n3100# c1_n3036_n3000# +X0 c1_n3036_n3000# m3_n3136_n3100# sky130_fd_pr__cap_mim_m3_1 l=3e+07u w=3e+07u +.ends + +.subckt sky130_fd_pr__pfet_g5v0d10v5_YEUEBV VSUBS w_n992_n497# a_n574_n200# a_n356_n200# ++ a_n138_n200# a_80_n200# a_n80_n297# a_734_n200# a_n734_n297# a_516_n200# a_574_n297# ++ a_n516_n297# a_356_n297# a_298_n200# a_n298_n297# a_138_n297# a_n792_n200# +X0 a_734_n200# a_574_n297# a_516_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X1 a_n356_n200# a_n516_n297# a_n574_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X2 a_n138_n200# a_n298_n297# a_n356_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X3 a_516_n200# a_356_n297# a_298_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X4 a_n574_n200# a_n734_n297# a_n792_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X5 a_298_n200# a_138_n297# a_80_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +X6 a_80_n200# a_n80_n297# a_n138_n200# w_n992_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_pr__pfet_g5v0d10v5_YUHPBG VSUBS a_n138_n200# w_n338_n497# a_80_n200# ++ a_n80_n297# +X0 a_80_n200# a_n80_n297# a_n138_n200# w_n338_n497# sky130_fd_pr__pfet_g5v0d10v5 w=2e+06u l=800000u +.ends + +.subckt sky130_fd_sc_hvl__inv_8 A VGND VNB VPB VPWR Y +X0 Y A VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X1 Y A VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X2 Y A VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X3 VPWR A Y VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X4 VPWR A Y VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X5 VPWR A Y VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X6 VGND A Y VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X7 VGND A Y VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X8 Y A VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X9 Y A VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X10 Y A VPWR VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X11 Y A VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X12 VPWR A Y VPB sky130_fd_pr__pfet_g5v0d10v5 w=1.5e+06u l=500000u +X13 VGND A Y VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X14 VGND A Y VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +X15 Y A VGND VNB sky130_fd_pr__nfet_g5v0d10v5 w=750000u l=500000u +.ends + +.subckt simple_por vdd3v3 vdd1v8 vss porb_h por_l porb_l +Xsky130_fd_pr__cap_mim_m3_2_W5U4AW_0 vss sky130_fd_sc_hvl__schmittbuf_1_0/A vss sky130_fd_pr__cap_mim_m3_2_W5U4AW +Xsky130_fd_sc_hvl__buf_8_1 out vss vss vdd1v8 vdd1v8 porb_l sky130_fd_sc_hvl__buf_8 +Xsky130_fd_pr__pfet_g5v0d10v5_ZEUEFZ_0 vss vdd3v3 m1_502_7653# vdd3v3 vdd3v3 vdd3v3 ++ m1_502_7653# m1_502_7653# m1_502_7653# m1_502_7653# vdd3v3 m1_502_7653# m1_502_7653# ++ m1_502_7653# vdd3v3 m1_502_7653# m1_502_7653# m1_502_7653# m1_502_7653# sky130_fd_pr__pfet_g5v0d10v5_ZEUEFZ +Xsky130_fd_pr__nfet_g5v0d10v5_TGFUGS_0 vss m1_721_6815# vss m1_721_6815# vss m1_721_6815# ++ m1_721_6815# m1_721_6815# m1_721_6815# m1_721_6815# m1_721_6815# m1_721_6815# vss ++ vss m1_721_6815# vss m1_721_6815# sky130_fd_pr__nfet_g5v0d10v5_TGFUGS +Xsky130_fd_pr__res_xhigh_po_0p69_S5N9F3_0 vss li_2935_165# vss li_4479_165# li_4866_5813# ++ li_7182_5813# li_5251_165# li_1778_5813# li_9111_165# li_3322_5813# li_9498_5813# ++ li_7567_165# li_7954_5813# li_9883_165# li_8726_5813# li_7182_5813# li_619_165# ++ li_5638_5813# li_1006_5813# li_2163_165# li_5638_5813# li_619_165# li_6795_165# ++ li_5251_165# li_3707_165# li_9498_5813# li_2163_165# li_4479_165# li_4866_5813# ++ vss li_4094_5813# li_2550_5813# li_2550_5813# li_4094_5813# li_8339_165# li_2935_165# ++ li_7954_5813# li_9883_165# vss li_6410_5813# li_8339_165# vss li_1778_5813# li_1006_5813# ++ vss li_6410_5813# li_6023_165# li_6795_165# li_3707_165# vdd3v3 li_1391_165# li_9111_165# ++ li_8726_5813# li_7567_165# li_6023_165# vss li_1391_165# li_3322_5813# sky130_fd_pr__res_xhigh_po_0p69_S5N9F3 +Xsky130_fd_pr__pfet_g5v0d10v5_3YBPVB_0 vss m1_2993_7658# vdd3v3 m1_721_6815# m1_185_6573# ++ sky130_fd_pr__pfet_g5v0d10v5_3YBPVB +Xsky130_fd_sc_hvl__schmittbuf_1_0 sky130_fd_sc_hvl__schmittbuf_1_0/A vss vss vdd3v3 ++ vdd3v3 out sky130_fd_sc_hvl__schmittbuf_1 +Xsky130_fd_pr__pfet_g5v0d10v5_3YBPVB_1 vss m1_2756_6573# vdd3v3 m1_4283_8081# m1_2756_6573# ++ sky130_fd_pr__pfet_g5v0d10v5_3YBPVB +Xsky130_fd_pr__pfet_g5v0d10v5_3YBPVB_2 vss m1_6249_7690# vdd3v3 sky130_fd_sc_hvl__schmittbuf_1_0/A ++ m1_2756_6573# sky130_fd_pr__pfet_g5v0d10v5_3YBPVB +Xsky130_fd_pr__pfet_g5v0d10v5_3YBPVB_3 vss m1_185_6573# vdd3v3 m1_502_7653# m1_185_6573# ++ sky130_fd_pr__pfet_g5v0d10v5_3YBPVB +Xsky130_fd_pr__pfet_g5v0d10v5_YUHPXE_0 vss vdd3v3 vdd3v3 m1_6249_7690# m1_4283_8081# ++ sky130_fd_pr__pfet_g5v0d10v5_YUHPXE +Xsky130_fd_pr__nfet_g5v0d10v5_PKVMTM_0 vss m1_721_6815# vss m1_2756_6573# vss sky130_fd_pr__nfet_g5v0d10v5_PKVMTM +Xsky130_fd_pr__nfet_g5v0d10v5_ZK8HQC_1 vss li_2550_5813# vss m1_185_6573# vss sky130_fd_pr__nfet_g5v0d10v5_ZK8HQC +Xsky130_fd_pr__cap_mim_m3_1_WRT4AW_0 vss vss sky130_fd_sc_hvl__schmittbuf_1_0/A sky130_fd_pr__cap_mim_m3_1_WRT4AW +Xsky130_fd_pr__pfet_g5v0d10v5_YEUEBV_0 vss vdd3v3 m1_4283_8081# vdd3v3 m1_4283_8081# ++ vdd3v3 m1_4283_8081# m1_4283_8081# m1_4283_8081# vdd3v3 m1_4283_8081# m1_4283_8081# ++ m1_4283_8081# m1_4283_8081# m1_4283_8081# m1_4283_8081# vdd3v3 sky130_fd_pr__pfet_g5v0d10v5_YEUEBV +Xsky130_fd_pr__pfet_g5v0d10v5_YUHPBG_0 vss vdd3v3 vdd3v3 m1_2993_7658# m1_502_7653# ++ sky130_fd_pr__pfet_g5v0d10v5_YUHPBG +Xsky130_fd_sc_hvl__inv_8_0 out vss vss vdd1v8 vdd1v8 por_l sky130_fd_sc_hvl__inv_8 +Xsky130_fd_sc_hvl__fill_4_0 vss vss vdd3v3 vdd3v3 sky130_fd_sc_hvl__fill_4 +Xsky130_fd_sc_hvl__buf_8_0 out vss vss vdd3v3 vdd3v3 porb_h sky130_fd_sc_hvl__buf_8 +.ends +
diff --git a/ngspice/simple_por/simple_por/simple_por_tb.spice b/ngspice/simple_por/simple_por/simple_por_tb.spice new file mode 100644 index 0000000..18fc1dc --- /dev/null +++ b/ngspice/simple_por/simple_por/simple_por_tb.spice
@@ -0,0 +1,51 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Simple POR circuit for Caravel +*------------------------------------------------------------------- +* +* Architecture: see simple_por.spice +* Response of this circuit by ngspice simulation is a ~15ms delay. +*------------------------------------------------------------------- + +.lib /home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice tt +.include /home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hvl/spice/sky130_fd_sc_hvl.spice +.include simple_por.spice + +*---------------------------- +* Testbench circuit +*---------------------------- +Vpwr vdda vss DC=0 PWL(0.0 0 100u 0 5m 3.3) +Vdig vccd vss DC=0 PWL(0.0 0 300u 0 5.3m 1.8) +Rgnd vss 0 0.01 +Cload1 porb_h vss 1E-12 +Cload2 por_l vss 1E-12 +Cload3 porb_l vss 1E-12 +Xpor vdda vccd vss porb_h por_l porb_l simple_por +*---------------------------- + +*---------------------------- +* Testbench control +*---------------------------- +.control +tran 10u 20m +plot porb_h +plot por_l +plot porb_l +.endc + +.end +
diff --git a/ngspice/simple_por/simple_por/threshold_test_tb.spice b/ngspice/simple_por/simple_por/threshold_test_tb.spice new file mode 100644 index 0000000..4d064d0 --- /dev/null +++ b/ngspice/simple_por/simple_por/threshold_test_tb.spice
@@ -0,0 +1,47 @@ +*--------------------------------------------------------------------------- +* SPDX-FileCopyrightText: 2020 Efabless Corporation +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* https://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +*--------------------------------------------------------------------------- +* Threshold test for POR circuit +* Determine gate voltage at which the HV NFET draws 240nA nominal +* +* Result: 0.7575V +*------------------------------------------------------------------- + +.lib /home/tim/projects/efabless/tech/SW/sky130A/libs.tech/ngspice/sky130.lib.spice tt + + +*---------------------------- +* Testbench circuit +*---------------------------- +Rtest vdda mir1 1MEG +Xm1 mir1 vin vss vss sky130_fd_pr__nfet_g5v0d10v5 w=2 l=0.8 + +Vgate vin vss DC=0 +Vpwr vdda vss DC=3.3 +Rgnd vss 0 0.1 + +*---------------------------- +* Testbench control +*---------------------------- +.control +* DC sweep from 0.7 to 0.8V +dc Vgate 0.7 0.8 0.001 +wrdata test.data Vpwr#branch vin + +.endc + +.end +
diff --git a/scripts/scripts/compositor.py b/scripts/scripts/compositor.py new file mode 100755 index 0000000..ec48636 --- /dev/null +++ b/scripts/scripts/compositor.py
@@ -0,0 +1,133 @@ +#!/bin/env python3 +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# +# compositor.py --- +# +# Compose the final GDS for caravel from the caravel GDS, seal ring +# GDS, and fill GDS. +# + +import sys +import os +import re +import subprocess + +def usage(): + print("compositor.py [layout_name] [-keep]") + return 0 + +if __name__ == '__main__': + + if len(sys.argv) == 1: + usage() + sys.exit(0) + + optionlist = [] + arguments = [] + + debugmode = False + keepmode = False + + for option in sys.argv[1:]: + if option.find('-', 0) == 0: + optionlist.append(option) + else: + arguments.append(option) + + if len(arguments) > 1: + print("Wrong number of arguments given to compositor.py.") + usage() + sys.exit(0) + + if len(arguments) == 1: + project = arguments[0] + else: + project = 'caravel' + + if '-debug' in optionlist: + debugmode = True + if '-keep' in optionlist: + keepmode = True + + magdir = '../mag' + rcfile = magdir + '/.magicrc' + + with open(magdir + '/compose_final.tcl', 'w') as ofile: + print('#!/bin/env wish', file=ofile) + print('drc off', file=ofile) + + print('load ' + project + ' -dereference', file=ofile) + print('select top cell', file=ofile) + + # Ceate a cell to represent the generated fill. There are + # no magic layers corresponding to the fill shape data, and + # it's gigabytes anyway, so we don't want to deal with any + # actual data. So it's just a placeholder. + + print('set bbox [box values]', file=ofile) + print('load ' + project + '_fill_pattern', file=ofile) + print('snap internal', file=ofile) + print('box values {*}$bbox', file=ofile) + print('paint comment', file=ofile) + print('property GDS_FILE ../gds/' + project + '_fill_pattern.gds', file=ofile) + print('property GDS_START 0', file=ofile) + print('property FIXED_BBOX "$bbox"', file=ofile) + + # Now go back to the project top level and place the fill cell. + print('load ' + project, file=ofile) + print('select top cell', file=ofile) + print('getcell ' + project + '_fill_pattern child 0 0', file=ofile) + + # Move existing origin to (6um, 6um) for seal ring placement + print('move origin -6um -6um', file=ofile) + + # Read in abstract view of seal ring + print('box position 0 0', file=ofile) + print('getcell advSeal_6um_gen', file=ofile) + + # Generate final GDS + print('puts stdout "Writing final GDS. . . "', file=ofile) + print('flush stdout', file=ofile) + print('gds write ../gds/' + project + '_final.gds', file=ofile) + print('quit -noprompt', file=ofile) + + myenv = os.environ.copy() + # Abstract views are appropriate for final composition + myenv['MAGTYPE'] = 'maglef' + + mproc = subprocess.run(['magic', '-dnull', '-noconsole', + '-rcfile', rcfile, magdir + '/compose_final.tcl'], + stdin = subprocess.DEVNULL, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + cwd = magdir, + env = myenv, + universal_newlines = True) + if mproc.stdout: + for line in mproc.stdout.splitlines(): + print(line) + if mproc.stderr: + print('Error message output from magic:') + for line in mproc.stderr.splitlines(): + print(line) + if mproc.returncode != 0: + print('ERROR: Magic exited with status ' + str(mproc.returncode)) + + if not keepmode: + os.remove(magdir + '/compose_final.tcl') + + exit(0)
diff --git a/scripts/scripts/generate_fill.py b/scripts/scripts/generate_fill.py new file mode 100755 index 0000000..6b4cbcd --- /dev/null +++ b/scripts/scripts/generate_fill.py
@@ -0,0 +1,111 @@ +#!/bin/env python3 +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# +# generate_fill.py --- +# +# Run the fill generation on the caravel top level. +# + +import sys +import os +import re +import subprocess + +def usage(): + print("generate_fill.py [layout_name] [-keep]") + return 0 + +if __name__ == '__main__': + + if len(sys.argv) == 1: + usage() + sys.exit(0) + + optionlist = [] + arguments = [] + + debugmode = False + keepmode = False + + for option in sys.argv[1:]: + if option.find('-', 0) == 0: + optionlist.append(option) + else: + arguments.append(option) + + if len(arguments) > 1: + print("Wrong number of arguments given to generate_fill.py.") + usage() + sys.exit(0) + + if len(arguments) == 1: + project = arguments[0] + else: + project = 'caravel' + + if '-debug' in optionlist: + debugmode = True + if '-keep' in optionlist: + keepmode = True + + magdir = '../mag' + rcfile = magdir + '/.magicrc' + + with open(magdir + '/generate_fill.tcl', 'w') as ofile: + print('#!/bin/env wish', file=ofile) + print('drc off', file=ofile) + print('load ' + project + ' -dereference', file=ofile) + print('select top cell', file=ofile) + print('expand', file=ofile) + + # Flatten into a cell with a new name + print('puts stdout "Flattening layout. . . "', file=ofile) + print('flatten -nolabels ' + project + '_fill_pattern', file=ofile) + print('load ' + project + '_fill_pattern', file=ofile) + + # Remove any GDS_FILE reference + print('property GDS_FILE ""', file=ofile) + print('cif ostyle wafflefill', file=ofile) + print('puts stdout "Writing GDS. . . "', file=ofile) + print('gds write ../gds/' + project + '_fill_pattern.gds', file=ofile) + print('quit -noprompt', file=ofile) + + myenv = os.environ.copy() + myenv['MAGTYPE'] = 'mag' + + mproc = subprocess.run(['magic', '-dnull', '-noconsole', + '-rcfile', rcfile, magdir + '/generate_fill.tcl'], + stdin = subprocess.DEVNULL, + stdout = subprocess.PIPE, + stderr = subprocess.PIPE, + cwd = magdir, + env = myenv, + universal_newlines = True) + if mproc.stdout: + for line in mproc.stdout.splitlines(): + print(line) + if mproc.stderr: + print('Error message output from magic:') + for line in mproc.stderr.splitlines(): + print(line) + if mproc.returncode != 0: + print('ERROR: Magic exited with status ' + str(mproc.returncode)) + + if not keepmode: + os.remove(magdir + '/generate_fill.tcl') + + exit(0)
diff --git a/scripts/scripts/set_user_id.py b/scripts/scripts/set_user_id.py new file mode 100755 index 0000000..3975354 --- /dev/null +++ b/scripts/scripts/set_user_id.py
@@ -0,0 +1,224 @@ +#!/bin/env python3 +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# +# set_user_id.py --- +# +# Manipulate the magic database, GDS, and verilog source files for the +# user_id_programming block to set the user ID number. +# +# The user ID number is a 32-bit value that is passed to this routine +# as an integer. +# +# user_id_programming layout map: +# Positions marked (in microns) for value = 0. For value = 1, move +# the via 0.92um to the left. +# +# Layout grid is 0.46um x 0.34um with half-pitch offset (0.23um, 0.17um) +# +# Signal Via position (um) +# name X Y +#-------------------------------- +# mask_rev[0] 14.49 9.35 +# mask_rev[1] 16.33 9.35 +# mask_rev[2] 10.35 20.23 +# mask_rev[3] 8.05 9.35 +# mask_rev[4] 28.29 9.35 +# mask_rev[5] 21.85 25.67 +# mask_rev[6] 8.05 20.23 +# mask_rev[7] 20.47 9.35 +# mask_rev[8] 17.25 17.85 +# mask_rev[9] 25.53 12.07 +# mask_rev[10] 22.31 20.23 +# mask_rev[11] 13.11 9.35 +# mask_rev[12] 23.69 23.29 +# mask_rev[13] 24.15 12.07 +# mask_rev[14] 13.57 17.85 +# mask_rev[15] 23.23 6.97 +# mask_rev[16] 24.15 17.85 +# mask_rev[17] 8.51 17.85 +# mask_rev[18] 23.69 20.23 +# mask_rev[19] 10.81 23.29 +# mask_rev[20] 14.95 6.97 +# mask_rev[21] 18.17 23.29 +# mask_rev[22] 21.39 17.85 +# mask_rev[23] 26.45 25.67 +# mask_rev[24] 9.89 17.85 +# mask_rev[25] 15.87 17.85 +# mask_rev[26] 26.45 17.85 +# mask_rev[27] 8.51 6.97 +# mask_rev[28] 10.81 9.35 +# mask_rev[29] 27.83 20.23 +# mask_rev[30] 16.33 23.29 +# mask_rev[31] 8.05 14.79 +#-------------------------------- + +import os +import sys +import re + +def usage(): + print("set_user_id.py <user_id_value> [<path_to_project>]") + return 0 + +if __name__ == '__main__': + + # Coordinate pairs in microns for the zero position on each bit + mask_rev = ( + (14.49, 9.35), (16.33, 9.35), (10.35, 20.23), ( 8.05, 9.35), + (28.29, 9.35), (21.85, 25.67), ( 8.05, 20.23), (20.47, 9.35), + (17.25, 17.85), (25.53, 12.07), (22.31, 20.23), (13.11, 9.35), + (23.69, 23.29), (24.15, 12.07), (13.57, 17.85), (23.23, 6.97), + (24.15, 17.85), ( 8.51, 17.85), (23.69, 20.23), (10.81, 23.29), + (14.95, 6.97), (18.17, 23.29), (21.39, 17.85), (26.45, 25.67), + ( 9.89, 17.85), (15.87, 17.85), (26.45, 17.85), ( 8.51, 6.97), + (10.81, 9.35), (27.83, 20.23), (16.33, 23.29), ( 8.05, 14.79)); + + optionlist = [] + arguments = [] + + debugmode = False + + for option in sys.argv[1:]: + if option.find('-', 0) == 0: + optionlist.append(option) + else: + arguments.append(option) + + if len(arguments) != 1 and len(arguments) != 2: + if len(arguments) != 0: + print("Wrong number of arguments given to cleanup_unref.py.") + usage() + sys.exit(0) + + if '-debug' in optionlist: + debugmode = True + + user_id_value = arguments[0] + + # Convert to binary + user_id_bits = '{0:032b}'.format(int(user_id_value)) + + if len(arguments) == 2: + user_project_path = arguments[1] + else: + user_project_path = os.getcwd() + + magpath = user_project_path + '/mag' + gdspath = user_project_path + '/gds' + vpath = user_project_path + '/verilog' + errors = 0 + + if os.path.isdir(gdspath): + + # Bytes leading up to via position are: + viarec = "00 06 0d 02 00 43 00 06 0e 02 00 2c 00 2c 10 03 " + viabytes = bytes.fromhex(viarec) + + # Read the GDS file. If a backup was made of the zero-value + # program, then use it. + + gdsbak = gdspath + '/user_id_prog_zero.gds' + gdsfile = gdspath + '/user_id_programming.gds' + + if os.path.isfile(gdsbak): + with open(gdsbak, 'rb') as ifile: + gdsdata = ifile.read() + else: + with open(gdsfile, 'rb') as ifile: + gdsdata = ifile.read() + + for i in range(0,32): + # Ignore any zero bits. + if user_id_bits[i] == '0': + continue + + coords = mask_rev[i] + xum = coords[0] + yum = coords[1] + + # Contact is 0.17 x 0.17, so add and subtract 0.085 to get + # the corner positions. + + xllum = xum - 0.085 + yllum = yum - 0.085 + xurum = xum + 0.085 + yurum = yum + 0.085 + + # Get the 4-byte hex values for the corner coordinates + xllnm = round(xllum * 1000) + yllnm = round(yllum * 1000) + xllhex = '{0:08x}'.format(xllnm) + yllhex = '{0:08x}'.format(yllnm) + xurnm = round(xurum * 1000) + yurnm = round(yurum * 1000) + xurhex = '{0:08x}'.format(xurnm) + yurhex = '{0:08x}'.format(yurnm) + + # Magic's GDS output for vias always starts at the lower left + # corner and goes counterclockwise, repeating the first point. + viaoldposdata = viarec + xllhex + yllhex + xurhex + yllhex + viaoldposdata += xurhex + yurhex + xllhex + yurhex + xllhex + yllhex + + # For "one" bits, the X position is moved 0.92 microns to the left + newxllum = xllum - 0.92 + newxurum = xurum - 0.92 + + # Get the 4-byte hex values for the new corner coordinates + newxllnm = round(newxllum * 1000) + newxllhex = '{0:08x}'.format(newxllnm) + newxurnm = round(newxurum * 1000) + newxurhex = '{0:08x}'.format(newxurnm) + + vianewposdata = viarec + newxllhex + yllhex + newxurhex + yllhex + vianewposdata += newxurhex + yurhex + newxllhex + yurhex + newxllhex + yllhex + + # Diagnostic + if debugmode: + print('Bit ' + str(i) + ':') + print('Via position ({0:3.2f}, {1:3.2f}) to ({2:3.2f}, {3:3.2f})'.format(xllum, yllum, xurum, yurum)) + print('Old hex string = ' + viaoldposdata) + print('New hex string = ' + vianewposdata) + + # Convert hex strings to byte arrays + viaoldbytedata = bytearray.fromhex(viaoldposdata) + vianewbytedata = bytearray.fromhex(vianewposdata) + + # Replace the old data with the new + if viaoldbytedata not in gdsdata: + print('Error: via not found for bit position ' + str(i)) + errors += 1 + else: + gdsdata = gdsdata.replace(viaoldbytedata, vianewbytedata) + + if errors == 0: + # Keep a copy of the original + if not os.path.isfile(gdsbak): + os.rename(gdsfile, gdsbak) + + with open(gdsfile, 'wb') as ofile: + ofile.write(gdsdata) + + print('Done!') + + else: + print('There were errors in processing. No file written.') + sys.exit(1) + + else: + print('No directory ' + gdspath + ' found.') + sys.exit(1) + sys.exit(0)
diff --git a/utils/utils/MAGIC.txt b/utils/utils/MAGIC.txt new file mode 100644 index 0000000..78b4d56 --- /dev/null +++ b/utils/utils/MAGIC.txt
@@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +#### + +1) You must set the PDK_ROOT variable + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export PDKPATH=$PDK_ROOT/sky130A ; + +2) Useful misc utils + + + +load caravel -dereference +drc style drc(full) +drc why +drc find 10 ; findbox zoom
diff --git a/utils/utils/README.txt b/utils/utils/README.txt new file mode 100644 index 0000000..78b4d56 --- /dev/null +++ b/utils/utils/README.txt
@@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +#### + +1) You must set the PDK_ROOT variable + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export PDKPATH=$PDK_ROOT/sky130A ; + +2) Useful misc utils + + + +load caravel -dereference +drc style drc(full) +drc why +drc find 10 ; findbox zoom
diff --git a/utils/utils/addmpwseal.tcl b/utils/utils/addmpwseal.tcl new file mode 100644 index 0000000..b562f93 --- /dev/null +++ b/utils/utils/addmpwseal.tcl
@@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +drc off +gds readonly true +gds rescale false +gds read ../gds/sram_1rw1r_32_256_8_sky130_lp1.gds +load ./caravel.mag +select top cell +move origin -7.165um -7.120um +box position 0 0 +getcell advSeal_6um_gen +gds write caravel.mpw.gds
diff --git a/utils/utils/core_scripts/README.md b/utils/utils/core_scripts/README.md new file mode 100644 index 0000000..b14c1db --- /dev/null +++ b/utils/utils/core_scripts/README.md
@@ -0,0 +1,20 @@ +<!--- +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +--> +# What is this? + +Core scripts are doing the actual work, scripts under ../scripts are the ones that should be used. \ No newline at end of file
diff --git a/utils/utils/core_scripts/magic-drc.sh b/utils/utils/core_scripts/magic-drc.sh new file mode 100644 index 0000000..5f5068d --- /dev/null +++ b/utils/utils/core_scripts/magic-drc.sh
@@ -0,0 +1,54 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./magic-drc.sh <target_path> <design_name> <pdk-root> <target-type> <pdk-name> <output_path> + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export TARGET_TYPE=$4 +export PDK=$5 +export OUT_DIR=$6 +export TCL_CALL_PATH=${7:-$(pwd)} + +echo "Running Magic..." +export MAGIC_MAGICRC=$PDK_ROOT/$PDK/libs.tech/magic/sky130A.magicrc + +magic \ + -noconsole \ + -dnull \ + -rcfile $MAGIC_MAGICRC \ + $TCL_CALL_PATH/magic-drc.tcl \ + </dev/null \ + |& tee $OUT_DIR/magic_drc.log + +TEST=$OUT_DIR/$DESIGN_NAME.magic.drc + +crashSignal=$(find $TEST) +if ! [[ $crashSignal ]]; then echo "DRC Check FAILED"; exit -1; fi + + +Test_Magic_violations=$(grep "COUNT: " $TEST -s | tail -1 | sed -r 's/[^0-9]*//g') +if ! [[ $Test_Magic_violations ]]; then Test_Magic_violations=-1; fi +if [ $Test_Magic_violations -ne -1 ]; then Test_Magic_violations=$(((Test_Magic_violations+3)/4)); fi + +echo "Test # of DRC Violations:" +echo $Test_Magic_violations + +if [ 0 -ne $Test_Magic_violations ]; then echo "DRC Check FAILED"; exit -1; fi + +echo "DRC Check Passed" +exit 0
diff --git a/utils/utils/core_scripts/magic-drc.tcl b/utils/utils/core_scripts/magic-drc.tcl new file mode 100755 index 0000000..6768d3c --- /dev/null +++ b/utils/utils/core_scripts/magic-drc.tcl
@@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +if { $::env(TARGET_TYPE) == "gds"} { + gds read $::env(TARGET_DIR)/$::env(DESIGN_NAME).gds +} else { + if { $::env(TARGET_TYPE) == "mag" } { + load $::env(TARGET_DIR)/$::env(DESIGN_NAME).mag + } else { + def read $::env(TARGET_DIR)/$::env(DESIGN_NAME).def + } +} + +set fout [open $::env(OUT_DIR)/$::env(DESIGN_NAME).magic.drc w] +set oscale [cif scale out] +set cell_name $::env(DESIGN_NAME) +magic::suspendall +puts stdout "\[INFO\]: Loading $cell_name\n" +flush stdout +load $cell_name +select top cell +drc euclidean on +drc style drc(full) +drc check +set drcresult [drc listall why] + + +set count 0 +puts $fout "$cell_name" +puts $fout "----------------------------------------" +foreach {errtype coordlist} $drcresult { + puts $fout $errtype + puts $fout "----------------------------------------" + foreach coord $coordlist { + set bllx [expr {$oscale * [lindex $coord 0]}] + set blly [expr {$oscale * [lindex $coord 1]}] + set burx [expr {$oscale * [lindex $coord 2]}] + set bury [expr {$oscale * [lindex $coord 3]}] + set coords [format " %.3f %.3f %.3f %.3f" $bllx $blly $burx $bury] + puts $fout "$coords" + set count [expr {$count + 1} ] + } + puts $fout "----------------------------------------" +} + +puts $fout "\[INFO\]: COUNT: $count" +puts $fout "\[INFO\]: Should be divided by 3 or 4" + +puts $fout "" +close $fout + +puts stdout "\[INFO\]: COUNT: $count" +puts stdout "\[INFO\]: Should be divided by 3 or 4" +puts stdout "\[INFO\]: DRC Checking DONE ($::env(OUT_DIR)/$::env(DESIGN_NAME).magic.drc)" +flush stdout + +puts stdout "\[INFO\]: Saving mag view with DRC errors($::env(OUT_DIR)/$::env(DESIGN_NAME).magic.drc.mag)" +# WARNING: changes the name of the cell; keep as last step +save $::env(OUT_DIR)/$::env(DESIGN_NAME).magic.drc.mag +puts stdout "\[INFO\]: Saved" + +exit 0
diff --git a/utils/utils/core_scripts/magic-ext.sh b/utils/utils/core_scripts/magic-ext.sh new file mode 100644 index 0000000..68bfc39 --- /dev/null +++ b/utils/utils/core_scripts/magic-ext.sh
@@ -0,0 +1,36 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./magic-ext.sh <target_path> <design_name> <pdk-root> <target-type> <pdk-name> <output_path> + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export TARGET_TYPE=$4 +export PDK=$5 +export OUT_DIR=$6 +export TCL_CALL_PATH=${7:-$(pwd)} + +echo "Running Magic..." +export MAGIC_MAGICRC=$PDK_ROOT/$PDK/libs.tech/magic/sky130A.magicrc + +magic \ + -noconsole \ + -dnull \ + -rcfile $MAGIC_MAGICRC \ + $TCL_CALL_PATH/magic-ext.tcl \ + </dev/null \ + |& tee $OUT_DIR/magic_ext.log
diff --git a/utils/utils/core_scripts/magic-ext.tcl b/utils/utils/core_scripts/magic-ext.tcl new file mode 100644 index 0000000..5a05dcb --- /dev/null +++ b/utils/utils/core_scripts/magic-ext.tcl
@@ -0,0 +1,44 @@ +#!/usr/bin/tclsh +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +puts "Performing Spice Extractions..." + +if { ![file isdirectory $::env(OUT_DIR)] } { + exec mkdir $::env(OUT_DIR)/ +} + + +if { $::env(TARGET_TYPE) == "gds"} { + gds read $::env(TARGET_DIR)/$::env(DESIGN_NAME).gds +} else { + if { $::env(TARGET_TYPE) == "mag" } { + load $::env(TARGET_DIR)/$::env(DESIGN_NAME).mag + } else { + def read $::env(TARGET_DIR)/$::env(DESIGN_NAME).def + } +} + +load $::env(DESIGN_NAME) -dereference +cd $::env(OUT_DIR)/ +extract do local +# extract warn all +extract +ext2spice lvs +ext2spice $::env(DESIGN_NAME).ext +feedback save $::env(OUT_DIR)/magic_extraction_feedback.txt + +puts "Done!" \ No newline at end of file
diff --git a/utils/utils/drc-def-sky130A.sh b/utils/utils/drc-def-sky130A.sh new file mode 100644 index 0000000..671b14a --- /dev/null +++ b/utils/utils/drc-def-sky130A.sh
@@ -0,0 +1,29 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./drc-def-sky130A.sh <target_path> <design_name> <pdk-root> [<output_path> default is <target_path>/results/] + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export OUT_DIR=${4:-$TARGET_DIR/results/} +export TCL_CALL_PATH=$(pwd)/core_scripts + +if ! [[ -d "$OUT_DIR" ]] +then + mkdir $OUT_DIR +fi +bash ./core_scripts/magic-drc.sh $TARGET_DIR $DESIGN_NAME $PDK_ROOT "def" "sky130A" $OUT_DIR $TCL_CALL_PATH
diff --git a/utils/utils/drc-gds-sky130A.sh b/utils/utils/drc-gds-sky130A.sh new file mode 100644 index 0000000..4c1d6d8 --- /dev/null +++ b/utils/utils/drc-gds-sky130A.sh
@@ -0,0 +1,30 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./drc-gds-sky130A.sh <target_path> <design_name> <pdk-root> [<output_path> default is <target_path>/results/] + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export OUT_DIR=${4:-$TARGET_DIR/results/} +export TCL_CALL_PATH=$(pwd)/core_scripts + +if ! [[ -d "$OUT_DIR" ]] +then + mkdir $OUT_DIR +fi + +bash ./core_scripts/magic-drc.sh $TARGET_DIR $DESIGN_NAME $PDK_ROOT "gds" "sky130A" $OUT_DIR $TCL_CALL_PATH
diff --git a/utils/utils/drc-mag-sky130A.sh b/utils/utils/drc-mag-sky130A.sh new file mode 100644 index 0000000..2bbecd3 --- /dev/null +++ b/utils/utils/drc-mag-sky130A.sh
@@ -0,0 +1,29 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./drc-mag-sky130A.sh <target_path> <design_name> <pdk-root> [<output_path> default is <target_path>/results/] + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export OUT_DIR=${4:-$TARGET_DIR/results/} +export TCL_CALL_PATH=$(pwd)/core_scripts + +if ! [[ -d "$OUT_DIR" ]] +then + mkdir $OUT_DIR +fi +bash ./core_scripts/magic-drc.sh $TARGET_DIR $DESIGN_NAME $PDK_ROOT "mag" "sky130A" $OUT_DIR $TCL_CALL_PATH
diff --git a/utils/utils/examples/README.md b/utils/utils/examples/README.md new file mode 100644 index 0000000..10f7a37 --- /dev/null +++ b/utils/utils/examples/README.md
@@ -0,0 +1,19 @@ +<!--- +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +--> +This folder contains miscelleneous useful scripts +THIS IS STILL WORK IN PROGRESSS - SUGGESTIONS ARE WELCOME THROUGH ISSUES
diff --git a/utils/utils/examples/addmpwseal.tcl b/utils/utils/examples/addmpwseal.tcl new file mode 100644 index 0000000..79e4b9e --- /dev/null +++ b/utils/utils/examples/addmpwseal.tcl
@@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +drc off +gds readonly true +gds read ../gds/sram_1rw1r_32_256_8_sky130_lp1.gds +load openram_tc_1kb.mag +select top cell +move origin -1015um -1272.5um +box position 0 0 +getcell advSeal_6um_gen +save +gds write ../gds/openram_tc_1kb.gds +
diff --git a/utils/utils/examples/create-project.sh b/utils/utils/examples/create-project.sh new file mode 100755 index 0000000..5b5b69c --- /dev/null +++ b/utils/utils/examples/create-project.sh
@@ -0,0 +1,38 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +cat <<'EOT' > .gitignore +.DS_Store +*.vcd +*.raw +*.vvp +a.out +EOT +mkdir scripts ; echo "This folder contains miscelleneous useful scripts" > scripts/README.md +mkdir def ; echo "This folder contains *.def files related to this project" > def/README.md +mkdir gds ; echo "This folder contains *.gds files related to this project" > gds/README.md +mkdir verilog ; echo "This folder contains *.v files related to this project" > verilog/README.md +mkdir mag ; echo "This folder contains *.mag files related to this project" > mag/README.md +mkdir lef ; echo "This folder contains *.lef files related to this project" > lef/README.md +mkdir macros ; echo "This folder contains subcell & macro files related to this project" > macros/README.md +mkdir doc ; echo "This folder contains documents related to this project" > doc/README.md +mkdir ngspice ; echo "This folder contains ngspice related files related to this project" > ngspice/README.md +mkdir openlane ; echo "This folder contains openlane related files related to this project" > openlane/README.md +mkdir pkg ; echo "This folder contains packaging-related files related to this project" > pkg/README.md +mkdir test ; echo "This folder contains test-related files related to this project" > test/README.md +mkdir xspice ; echo "This folder contains xspice files related to this project" > xspice/README.md +mkdir spi ; echo "This folder contains *.spi files related to this project" > spi/README.md +mkdir qflow ; echo "This folder contains qflow-related files related to this project" > qflow/README.md
diff --git a/utils/utils/examples/dot.magicrc b/utils/utils/examples/dot.magicrc new file mode 100644 index 0000000..42f2fb2 --- /dev/null +++ b/utils/utils/examples/dot.magicrc
@@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +puts stdout "Sourcing design .magicrc for technology sky130A ..." + +# Put grid on 0.005 pitch. This is important, as some commands don't +# rescale the grid automatically (such as lef read?). + +set scalefac [tech lambda] +if {[lindex $scalefac 1] < 2} { + scalegrid 1 2 +} + +# drc off +drc euclidean on + +# default pdk +# set SW_PDK_ROOT "/ef/tech/SW.2" +set PDK "sky130A" +set SCL_VARIANT "sky130_fd_sc_hd" +set IO_VARIANT "sky130_fd_io" +set PDKPATH "$::env(SW_PDK_ROOT)/$PDK" + +# loading technology +tech load "$PDKPATH/libs.tech/magic/current/$PDK.tech" + +# load device generator +source "$PDKPATH/libs.tech/magic/current/$PDK.tcl" + + +# load bind keys (optional) +source "$PDKPATH/libs.tech/magic/current/$PDK-BindKeys" + +# set units to lambda grid +snap lambda + +# add path to reference cells +set MAGPATH "$PDKPATH/libs.ref/$SCL_VARIANT/mag/*.mag" + + +addpath "$PDKPATH/libs.ref/sky130_fd_pr_base/mag" +addpath "$PDKPATH/libs.ref/$IO_VARIANT/mag" +addpath "$PDKPATH/libs.ref/$SCL_VARIANT/mag" + +# addpath ${MAGPATH}/s8fmlt + +# add path to GDS cells + +# add path to IP from catalog. This procedure defined in the PDK script. +catch {magic::query_mylib_ip} +# add path to local IP from user design space. Defined in the PDK script. +catch {magic::query_my_projects}
diff --git a/utils/utils/examples/drc-mag.sh b/utils/utils/examples/drc-mag.sh new file mode 100644 index 0000000..7229f45 --- /dev/null +++ b/utils/utils/examples/drc-mag.sh
@@ -0,0 +1,40 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export MAGTYPE=mag ; +export BASE=/home/mk/zooz/ ; +export PDKPATH=$BASE/pdks/ef-skywater-s8/EFS8A ; + +magic -dnull -noconsole -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc <<EOF +gds polygon subcell true +gds warning default +gds read $1.gds +load $1 +cellname delete \(UNNAMED\) +writeall force +select top cell +expand +drc on +drc euclidean on +drc check +drc catchup +drc listall +drc listall why +drc count total +drc count +quit -noprompt +EOF
diff --git a/utils/utils/examples/drc-maglef.sh b/utils/utils/examples/drc-maglef.sh new file mode 100644 index 0000000..42f622f --- /dev/null +++ b/utils/utils/examples/drc-maglef.sh
@@ -0,0 +1,40 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export MAGTYPE=maglef ; +export BASE=/home/mk/zooz/ ; +export PDKPATH=$BASE/pdks/ef-skywater-s8/EFS8A ; + +magic -dnull -noconsole -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc <<EOF +gds polygon subcell true +gds warning default +gds read $1.gds +load $1 +cellname delete \(UNNAMED\) +writeall force +select top cell +expand +drc on +drc euclidean on +drc check +drc catchup +drc listall +drc listall why +drc count total +drc count +quit -noprompt +EOF
diff --git a/utils/utils/examples/drc.sh b/utils/utils/examples/drc.sh new file mode 100755 index 0000000..7229f45 --- /dev/null +++ b/utils/utils/examples/drc.sh
@@ -0,0 +1,40 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export MAGTYPE=mag ; +export BASE=/home/mk/zooz/ ; +export PDKPATH=$BASE/pdks/ef-skywater-s8/EFS8A ; + +magic -dnull -noconsole -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc <<EOF +gds polygon subcell true +gds warning default +gds read $1.gds +load $1 +cellname delete \(UNNAMED\) +writeall force +select top cell +expand +drc on +drc euclidean on +drc check +drc catchup +drc listall +drc listall why +drc count total +drc count +quit -noprompt +EOF
diff --git a/utils/utils/examples/edit.tcl b/utils/utils/examples/edit.tcl new file mode 100644 index 0000000..f1766ad --- /dev/null +++ b/utils/utils/examples/edit.tcl
@@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +drc off +puts "Small delay..." +set macro_mags "digital_pll.mag lvlshiftdown.mag striVe2_soc.mag striVe_clkrst.mag striVe_spi.mag" + +gds readonly yes +gds rescale no +gds read ../gds/sram_1rw1r_32_256_8_sky130.gds +lef read ../lef/sram.abs.lef +foreach ff $macro_mags { drc off; load $ff -dereference; after 1000; select top cell; property LEFview TRUE } +load striVe2 -dereference +select top cell
diff --git a/utils/utils/examples/ext-gds.sh b/utils/utils/examples/ext-gds.sh new file mode 100644 index 0000000..c3efd7e --- /dev/null +++ b/utils/utils/examples/ext-gds.sh
@@ -0,0 +1,43 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export MAGTYPE=maglef ; +export BASE=/home/mk/zooz/ ; +export PDKPATH=$BASE/pdks/ef-skywater-s8/EFS8A ; + +magic -dnull -noconsole -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc <<EOF +gds polygon subcell true +gds warning default +gds read $1.gds +load $1.mag +save $1.mag +writeall force +select top cell +extract style ngspice(si) +extract +ext2spice hierarchy on +ext2spice format ngspice +ext2spice cthresh infinite +ext2spice rthresh infinite +ext2spice renumber offS +ext2spice scale off +ext2spice blackbox on +ext2spice subcircuit top auto +ext2spice global off +ext2spice $1.ext +quit -noprompt +EOF
diff --git a/utils/utils/examples/ext-mag.sh b/utils/utils/examples/ext-mag.sh new file mode 100644 index 0000000..a62a831 --- /dev/null +++ b/utils/utils/examples/ext-mag.sh
@@ -0,0 +1,40 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export MAGTYPE=mag ; +export BASE=/home/mk/zooz/ ; +export PDKPATH=$BASE/pdks/ef-skywater-s8/EFS8A ; + +magic -dnull -noconsole -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc <<EOF +load $1.mag +save $1.mag +writeall force +select top cell +extract style ngspice(si) +extract +ext2spice hierarchy on +ext2spice format ngspice +ext2spice cthresh infinite +ext2spice rthresh infinite +ext2spice renumber offS +ext2spice scale off +ext2spice blackbox on +ext2spice subcircuit top auto +ext2spice global off +ext2spice $1.ext +quit -noprompt +EOF
diff --git a/utils/utils/examples/ext.sh b/utils/utils/examples/ext.sh new file mode 100644 index 0000000..b414e8b --- /dev/null +++ b/utils/utils/examples/ext.sh
@@ -0,0 +1,43 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export MAGTYPE=maglef ; +export BASE=/home/mk/zooz/ ; +export PDKPATH=$BASE/pdks/ef-skywater-s8/EFS8A ; + +magic -dnull -noconsole -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc <<EOF +gds polygon subcell true +gds warning default +gds read $1.gds +load $1.mag +save $1.mag +writeall force +select top cell +extract style ngspice(si) +extract +ext2spice hierarchy on +ext2spice format ngspice +ext2spice cthresh infinite +ext2spice rthresh infinite +ext2spice renumber off +ext2spice scale off +ext2spice blackbox on +ext2spice subcircuit top auto +ext2spice global off +ext2spice $1.ext +quit -noprompt +EOF
diff --git a/utils/utils/examples/extract.tcl b/utils/utils/examples/extract.tcl new file mode 100644 index 0000000..a38c9cb --- /dev/null +++ b/utils/utils/examples/extract.tcl
@@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +lef read $::env(PDKPATH)/libs.ref/techLEF/scs8hd/scs8hd_tech.lef +set macro_mags "openram_tc_core.mag" + +# lef read ../lef/sram_1rw1r_32_256_8_sky130_lp1.lef + +foreach ff $macro_mags { drc off; after 500; load $ff -dereference; select top cell; property LEFview TRUE } + +load openram_tc_1kb -dereference + +select top cell +extract do local +extract +ext2spice lvs +ext2spice openram_tc_1kb.ext +feedback save extract.tcl.log +exit
diff --git a/utils/utils/examples/lvs.sh b/utils/utils/examples/lvs.sh new file mode 100755 index 0000000..3a5043e --- /dev/null +++ b/utils/utils/examples/lvs.sh
@@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +/ef/apps/bin/netgen -noconsole << EOF +readnet spice $1.spice +readnet spice $1.sp +lvs {$1.spice sram_2_16_sky130} {sram_2_16_sky130.sp sram_2_16_sky130} setup.tcl sram_2_16_sky130.lvs.report +quit +EOF
diff --git a/utils/utils/examples/mag2gds.tcl b/utils/utils/examples/mag2gds.tcl new file mode 100644 index 0000000..8d7057d --- /dev/null +++ b/utils/utils/examples/mag2gds.tcl
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# assumes an /ef tree or at least a symlink +drc off +gds readonly true +gds rescale false +set ::env(MAGTYPE) mag + +# gds read <hard macros read as-is.gds> +gds read ../gds/sram_1rw1r_32_256_8_sky130_lp1.gds + +load sram_1rw1r_32_256_8_sky130 -dereference +load openram_tc_core -dereference +load openram_tc_1kb -dereference + +select top cell + +cif *hier write disable + +gds write openram_tc_1kb.gds
diff --git a/utils/utils/examples/magic_drc.tcl b/utils/utils/examples/magic_drc.tcl new file mode 100755 index 0000000..554a4c6 --- /dev/null +++ b/utils/utils/examples/magic_drc.tcl
@@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 +set ::env(DESIGN_NAME) openram_tc_1kb +drc off +lef read ../lef/sram_1rw1r_32_256_8_sky130_lp1.lef +load sram_1rw1r_32_256_8_sky130 -dereference +load openram_tc_core -dereference +load openram_tc_1kb -dereference + +drc style drc(full) +drc euclidean on + +set fout [open drc.log w] +set oscale [cif scale out] +set cell_name $::env(DESIGN_NAME) +magic::suspendall +puts stdout "\[INFO\]: Loading $cell_name\n" +flush stdout +load $cell_name +select top cell +drc check +set drcresult [drc listall why] + + +set count 0 +puts $fout "$cell_name" +puts $fout "----------------------------------------" +foreach {errtype coordlist} $drcresult { + puts $fout $errtype + puts $fout "----------------------------------------" + foreach coord $coordlist { + set bllx [expr {$oscale * [lindex $coord 0]}] + set blly [expr {$oscale * [lindex $coord 1]}] + set burx [expr {$oscale * [lindex $coord 2]}] + set bury [expr {$oscale * [lindex $coord 3]}] + set coords [format " %.3f %.3f %.3f %.3f" $bllx $blly $burx $bury] + puts $fout "$coords" + set count [expr {$count + 1} ] + } + puts $fout "----------------------------------------" +} + +puts $fout "\[INFO\]: COUNT: $count" +puts $fout "\[INFO\]: Should be divided by 3 or 4" + +puts $fout "" +close $fout + +puts stdout "\[INFO\]: COUNT: $count" +puts stdout "\[INFO\]: Should be divided by 3 or 4" +puts stdout "\[INFO\]: DRC Checking DONE ($::env(DESIGN_NAME).drc)" +flush stdout + +puts stdout "\[INFO\]: Saving mag view with DRC errors($::env(DESIGN_NAME).drc.mag)" +# WARNING: changes the name of the cell; keep as last step +save $::env(DESIGN_NAME).drc.mag +puts stdout "\[INFO\]: Saved" + +exit 0
diff --git a/utils/utils/examples/pfg.sh b/utils/utils/examples/pfg.sh new file mode 100755 index 0000000..9d8def1 --- /dev/null +++ b/utils/utils/examples/pfg.sh
@@ -0,0 +1,38 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export PDKPATH=/home/mk/zooz/pdks/ef-skywater-s8/EFS8A +export MAGTYPE=mag + +padring \ +-L $PDKPATH/libs.ref/lef/s8iom0s8/s8iom0s8.lef \ +-L $PDKPATH/libs.ref/lef/s8iom0s8/power_pads_lib.lef \ +--def padframe.def padframe.cfg + +magic -rcfile $PDKPATH/libs.tech/magic/current/EFS8A.magicrc -noc -dnull <<EOF +def read padframe.def +save padframe +select top cell +lef write padframe.lef +gds write padframe.gds +exit +EOF + + + + +
diff --git a/utils/utils/examples/run_openram_tc_1kb.sh b/utils/utils/examples/run_openram_tc_1kb.sh new file mode 100755 index 0000000..408ce96 --- /dev/null +++ b/utils/utils/examples/run_openram_tc_1kb.sh
@@ -0,0 +1,23 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# +# Run netgen on striVe (top level) +# + +NETGEN_SETUP=$PDK_ROOT/EFS8A/libs.tech/netgen/EFS8A_setup.tcl + +netgen -batch lvs "../spi/openram_tc_1kb.spice openram_tc_1kb" "../verilog/gl/openram_tc_1kb.synthesis.v openram_tc_1kb" ${NETGEN_SETUP} openram_tc_1kb_comp.out -json | tee openram_tc_1kb_comp_lvs.log
diff --git a/utils/utils/examples/setup.tcl b/utils/utils/examples/setup.tcl new file mode 100644 index 0000000..193dd2f --- /dev/null +++ b/utils/utils/examples/setup.tcl
@@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# We must flatten these because the ports are disconnected +flatten class {-circuit1 dummy_cell_6t} +flatten class {-circuit1 dummy_cell_1rw_1r} +flatten class {-circuit1 dummy_cell_1w_1r} +flatten class {-circuit1 bitcell_array_0} +flatten class {-circuit1 pbitcell_0} +flatten class {-circuit1 pbitcell_1} +property {-circuit1 nshort} remove as ad ps pd +property {-circuit1 pshort} remove as ad ps pd +property {-circuit2 nshort} remove as ad ps pd +property {-circuit2 pshort} remove as ad ps pd +permute transistors
diff --git a/utils/utils/examples/wrap.tcl b/utils/utils/examples/wrap.tcl new file mode 100644 index 0000000..fc2c87e --- /dev/null +++ b/utils/utils/examples/wrap.tcl
@@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +drc off +gds readonly yes +gds rescale no + +gds read ../macros/sram/riscv-sky130/sram_1rw1r_32_256_8_sky130.gds +load sram_1rw1r_32_256_8_sky130 + +select top cell +property LEFview "TRUE" + +save pk_sram_1rw1r_32_256_8_sky130.mag + +# exec sed -i -E "/^.*GDS_END.*$/d" sram_1rw1r_32_256_8_sky130_original.mag
diff --git a/utils/utils/examples/wrap2.tcl b/utils/utils/examples/wrap2.tcl new file mode 100644 index 0000000..db1db3c --- /dev/null +++ b/utils/utils/examples/wrap2.tcl
@@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +drc off +gds readonly yes +gds rescale no + +lef read ../lef/sram.abs.con.lef +load sram_1rw1r_32_256_8_sky130 + +select top cell +expand +property LEFview "" +property LEFsymmetry "" +property LEFclass "" + +box position 5um 5um +getcell pk_sram_1rw1r_32_256_8_sky130 + +save sram_1rw1r_32_256_8_sky130.mag + +gds write output.gds + +save
diff --git a/utils/utils/examples/xor.drc b/utils/utils/examples/xor.drc new file mode 100644 index 0000000..14896ee --- /dev/null +++ b/utils/utils/examples/xor.drc
@@ -0,0 +1,42 @@ +# A general XOR script +# (https://www.klayout.de/forum/discussion/100/xor-vs-diff-tool) +# This script uses KLayout's DRC language to implement a generic +# XOR between two layouts. The name of the layouts is given +# in $a and $b. + +# For layout-to-layout XOR with multiple cores, run this script with +# ./klayout -r xor.drc -rd thr=NUM_CORES -rd top_cell=TOP_CELL_NAME -rd a=a.gds -rd b=b.gds -rd ol=xor.gds -zz +# (replace NUM_CORES by the desired number of cores to utilize + +# enable timing output +verbose + +# set up input a +a = source($a, $top_cell) + +# set up input b +b = source($b, $top_cell) + +$o && report("XOR #{$a} vs. #{$b}", $o) +$ol && target($ol, $co || "XOR") + +$thr && threads($thr) || threads(2) + +# collect all common layers +layers = {} +[ a.layout, b.layout ].each do |ly| + ly.layer_indices.each do |li| + i = ly.get_info(li) + layers[i.to_s] = i + end +end + +# perform the XOR's +layers.keys.sort.each do |l| + i = layers[l] + info("--- Running XOR for #{l} ---") + x = a.input(l) ^ b.input(l) + info("XOR differences: #{x.data.size}") + $o && x.output(l, "XOR results for layer #{l}") + $ol && x.output(i.layer, i.datatype, i.name) +end
diff --git a/utils/utils/examples/xor.sh b/utils/utils/examples/xor.sh new file mode 100755 index 0000000..6911062 --- /dev/null +++ b/utils/utils/examples/xor.sh
@@ -0,0 +1,22 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +: ${1?"Usage: $0 file1.gds file2.gds <top_level_module_name>"} +: ${2?"Usage: $0 file1.gds file2.gds <top_level_module_name>"} +: ${3?"Usage: $0 file1.gds file2.gds <top_level_module_name>"} + +klayout -r $(dirname $0)/xor.drc -rd top_cell=$3 -rd a=$1 -rd b=$2 -rd thr=$(nproc) -rd ol=xor.gds -zz
diff --git a/utils/utils/ext-def-sky130A.sh b/utils/utils/ext-def-sky130A.sh new file mode 100644 index 0000000..51ec955 --- /dev/null +++ b/utils/utils/ext-def-sky130A.sh
@@ -0,0 +1,30 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./ext-def-sky130A.sh <target_path> <design_name> <pdk-root> [<output_path> default is <target_path>/results/] + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export OUT_DIR=${4:-$TARGET_DIR/results/} +export TCL_CALL_PATH=$(pwd)/core_scripts + +if ! [[ -d "$OUT_DIR" ]] +then + mkdir $OUT_DIR +fi + +bash ./core_scripts/magic-ext.sh $TARGET_DIR $DESIGN_NAME $PDK_ROOT "def" "sky130A" $OUT_DIR $TCL_CALL_PATH
diff --git a/utils/utils/ext-gds-sky130A.sh b/utils/utils/ext-gds-sky130A.sh new file mode 100644 index 0000000..35071b8 --- /dev/null +++ b/utils/utils/ext-gds-sky130A.sh
@@ -0,0 +1,30 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./ext-gds-sky130A.sh <target_path> <design_name> <pdk-root> [<output_path> default is <target_path>/results/] + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export OUT_DIR=${4:-$TARGET_DIR/results/} +export TCL_CALL_PATH=$(pwd)/core_scripts + +if ! [[ -d "$OUT_DIR" ]] +then + mkdir $OUT_DIR +fi + +bash ./core_scripts/magic-ext.sh $TARGET_DIR $DESIGN_NAME $PDK_ROOT "gds" "sky130A" $OUT_DIR $TCL_CALL_PATH
diff --git a/utils/utils/ext-mag-sky130A.sh b/utils/utils/ext-mag-sky130A.sh new file mode 100644 index 0000000..b57ec31 --- /dev/null +++ b/utils/utils/ext-mag-sky130A.sh
@@ -0,0 +1,30 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# To call: ./ext-mag-sky130A.sh <target_path> <design_name> <pdk-root> [<output_path> default is <target_path>/results/] + +export TARGET_DIR=$1 +export DESIGN_NAME=$2 +export PDK_ROOT=$3 +export OUT_DIR=${4:-$TARGET_DIR/results/} +export TCL_CALL_PATH=$(pwd)/core_scripts + +if ! [[ -d "$OUT_DIR" ]] +then + mkdir $OUT_DIR +fi + +bash ./core_scripts/magic-ext.sh $TARGET_DIR $DESIGN_NAME $PDK_ROOT "mag" "sky130A" $OUT_DIR $TCL_CALL_PATH
diff --git a/utils/utils/gds2mag-mag.local.sh b/utils/utils/gds2mag-mag.local.sh new file mode 100755 index 0000000..110358b --- /dev/null +++ b/utils/utils/gds2mag-mag.local.sh
@@ -0,0 +1,37 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export MAGTYPE=mag ; +export PDKPATH=$PDK_ROOT/sky130A ; +export MAGIC=magic + + +$MAGIC -dnull -noconsole << EOF +#------------------------------------------------------ +drc off +#---------------------------------gds polygon subcell true +gds warning default +gds readonly true +gds rescale false +#---------------------------------tech unlock * +gds read $1 +load ${1%.gds} +#---------------------------------readspice ${1%.gds}.sp +cellname delete "(UNNAMED)" +save ${1%.gds}.mag +quit -noprompt +EOF
diff --git a/utils/utils/gds2mag-mag.sh b/utils/utils/gds2mag-mag.sh new file mode 100755 index 0000000..d53b156 --- /dev/null +++ b/utils/utils/gds2mag-mag.sh
@@ -0,0 +1,37 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export MAGTYPE=mag ; +export PDKPATH=$PDK_ROOT/sky130A ; +export MAGIC=magic + + +$MAGIC -rcfile $PDKPATH/libs.tech/magic/current/sky130A.magicrc -dnull -noconsole << EOF +#------------------------------------------------------ +drc off +#---------------------------------gds polygon subcell true +gds warning default +gds readonly true +gds rescale false +#---------------------------------tech unlock * +gds read $1 +load ${1%.gds} +#---------------------------------readspice ${1%.gds}.sp +cellname delete "(UNNAMED)" +save ${1%.gds}.mag +quit -noprompt +EOF
diff --git a/utils/utils/lef2maglef.sh b/utils/utils/lef2maglef.sh new file mode 100755 index 0000000..455c4a6 --- /dev/null +++ b/utils/utils/lef2maglef.sh
@@ -0,0 +1,60 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export MAGTYPE=mag ; +export PDKPATH=$PDK_ROOT/sky130A ; +export MAGIC=magic + + +$MAGIC -rcfile $PDKPATH/libs.tech/magic/current/sky130A.magicrc -dnull -noconsole << EOX +drc off +lef read $1.lef +load $1 +save $1.lef.mag +#writeall force $1.lef.mag + + # copy GDS properties from the MAG view into the MAGLEF view + set gds_properties [list] + set fp [open $1.mag r] + set mag_lines [split [read \$fp] "\n"] + foreach line \$mag_lines { + if { [string first "string GDS_" \$line] != -1 } { + lappend gds_properties \$line + } + } + close \$fp + set fp [open $1.lef.mag r] + set mag_lines [split [read \$fp] "\n"] + set new_mag_lines [list] + foreach line \$mag_lines { + if { [string first "<< end >>" \$line] != -1 } { + lappend new_mag_lines [join \$gds_properties "\n"] + } + lappend new_mag_lines \$line + } + close \$fp + set fp [open $1.lef.mag w] + puts \$fp [join \$new_mag_lines "\n"] + close \$fp + + +quit +EOX + +mv -f $1.lef.mag ../maglef/$1.mag +rm -f $1.lef
diff --git a/utils/utils/mag2maglef-mag.sh b/utils/utils/mag2maglef-mag.sh new file mode 100755 index 0000000..2934887 --- /dev/null +++ b/utils/utils/mag2maglef-mag.sh
@@ -0,0 +1,68 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export MAGTYPE=mag ; +export PDKPATH=$PDK_ROOT/sky130A ; +export MAGIC=magic + +$MAGIC -rcfile $PDKPATH/libs.tech/magic/current/sky130A.magicrc -dnull -noconsole <<EOF +drc off +load $1.mag +select top cell +expand +lef write $1.lef -hide +quit -noprompt +EOF + +$MAGIC -rcfile $PDKPATH/libs.tech/magic/current/sky130A.magicrc -dnull -noconsole << EOX +drc off +lef read $1.lef +load $1 +save $1.lef.mag +#writeall force $1.lef.mag + + # copy GDS properties from the MAG view into the MAGLEF view + set gds_properties [list] + set fp [open $1.mag r] + set mag_lines [split [read \$fp] "\n"] + foreach line \$mag_lines { + if { [string first "string GDS_" \$line] != -1 } { + lappend gds_properties \$line + } + } + close \$fp + set fp [open $1.lef.mag r] + set mag_lines [split [read \$fp] "\n"] + set new_mag_lines [list] + foreach line \$mag_lines { + if { [string first "<< end >>" \$line] != -1 } { + lappend new_mag_lines [join \$gds_properties "\n"] + } + lappend new_mag_lines \$line + } + close \$fp + set fp [open $1.lef.mag w] + puts \$fp [join \$new_mag_lines "\n"] + close \$fp + + +quit +EOX + +mv -f $1.lef.mag ../maglef/$1.mag +rm -f $1.lef
diff --git a/utils/utils/mag2maglef-maglef.localrc.sh b/utils/utils/mag2maglef-maglef.localrc.sh new file mode 100755 index 0000000..f167252 --- /dev/null +++ b/utils/utils/mag2maglef-maglef.localrc.sh
@@ -0,0 +1,68 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export MAGTYPE=maglef ; +export PDKPATH=$PDK_ROOT/sky130A ; +export MAGIC=magic + +$MAGIC -dnull -noconsole <<EOF +drc off +load $1.mag +select top cell +expand +lef write $1.lef -hide +quit -noprompt +EOF + +$MAGIC -dnull -noconsole << EOX +drc off +lef read $1.lef +load $1 +save $1.lef.mag +#writeall force $1.lef.mag + + # copy GDS properties from the MAG view into the MAGLEF view + set gds_properties [list] + set fp [open $1.mag r] + set mag_lines [split [read \$fp] "\n"] + foreach line \$mag_lines { + if { [string first "string GDS_" \$line] != -1 } { + lappend gds_properties \$line + } + } + close \$fp + set fp [open $1.lef.mag r] + set mag_lines [split [read \$fp] "\n"] + set new_mag_lines [list] + foreach line \$mag_lines { + if { [string first "<< end >>" \$line] != -1 } { + lappend new_mag_lines [join \$gds_properties "\n"] + } + lappend new_mag_lines \$line + } + close \$fp + set fp [open $1.lef.mag w] + puts \$fp [join \$new_mag_lines "\n"] + close \$fp + + +quit +EOX + +mv -f $1.lef.mag ../maglef/$1.mag +rm -f $1.lef
diff --git a/utils/utils/mag2maglef-maglef.sh b/utils/utils/mag2maglef-maglef.sh new file mode 100755 index 0000000..e70fbd3 --- /dev/null +++ b/utils/utils/mag2maglef-maglef.sh
@@ -0,0 +1,68 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + + +export PDK_ROOT=~/foss/pdks/open_pdks/sky130; +export MAGTYPE=maglef ; +export PDKPATH=$PDK_ROOT/sky130A ; +export MAGIC=magic + +$MAGIC -rcfile $PDKPATH/libs.tech/magic/current/sky130A.magicrc -dnull -noconsole <<EOF +drc off +load $1.mag +select top cell +expand +lef write $1.lef +quit -noprompt +EOF + +$MAGIC -rcfile $PDKPATH/libs.tech/magic/current/sky130A.magicrc -dnull -noconsole << EOX +drc off +lef read $1.lef +load $1 +save $1.lef.mag +#writeall force $1.lef.mag + + # copy GDS properties from the MAG view into the MAGLEF view + set gds_properties [list] + set fp [open $1.mag r] + set mag_lines [split [read \$fp] "\n"] + foreach line \$mag_lines { + if { [string first "string GDS_" \$line] != -1 } { + lappend gds_properties \$line + } + } + close \$fp + set fp [open $1.lef.mag r] + set mag_lines [split [read \$fp] "\n"] + set new_mag_lines [list] + foreach line \$mag_lines { + if { [string first "<< end >>" \$line] != -1 } { + lappend new_mag_lines [join \$gds_properties "\n"] + } + lappend new_mag_lines \$line + } + close \$fp + set fp [open $1.lef.mag w] + puts \$fp [join \$new_mag_lines "\n"] + close \$fp + + +quit +EOX + +mv -f $1.lef.mag ../maglef/$1.mag +rm -f $1.lef
diff --git a/utils/utils/magicDrc b/utils/utils/magicDrc new file mode 100755 index 0000000..fa6f783 --- /dev/null +++ b/utils/utils/magicDrc
@@ -0,0 +1,888 @@ +#!/bin/bash +# SPDX-FileCopyrightText: 2015, 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2015, 2020 efabless Corporation. All Rights Reserved. +# filter out most options, so magic Natively sees/handles *only* -T <file>. +# for-bash\ + declare -a C ; declare -a N ; export _CE= _NE= _M0= ;\ + for i in "$@" ; do _M0="$_M0${_M0:+ }\"${i//\"/\\\"}\""; done ;\ + while getopts "NFT:S:l:P:" o; do \ + : echo got "optchar $o, with optarg $OPTARG" ;\ + case "$o" in S) \ + C+=(-${o} "$OPTARG") ;\ + continue ; esac ;\ + case "$o" in P) \ + C+=(-${o} "$OPTARG") ;\ + continue ; esac ;\ + case "$o" in F|N) \ + C+=(-${o}) ;\ + continue ; esac ;\ + case "$o" in l) \ + C+=(-${o} "$OPTARG") ;\ + continue ; esac ;\ + case "$o" in T) \ + N+=(-${o} "$OPTARG") ;\ + continue ; esac ;\ + done ;\ + shift $((OPTIND-1)) ;\ + for i in "${C[@]}" ; do _CE="$_CE${_CE:+ }\"${i//\"/\\\"}\""; done ;\ + for i in "${N[@]}" ; do _NE="$_NE${_NE:+ }\"${i//\"/\\\"}\""; done ;\ + exec magic -dnull -noconsole "${N[@]}" <"$0" +# for-magic: +# magicDrc: run magic-DRC in batch on a .mag file, tabulate/pareto the error counts. +# +# magicDrc [-T <techfilePath>] [-S <drcStyleName>] [-P <N> ] [-l FILE_NAME] <magFileName> +# -T name specific techfile (def .tech extension), passed to magic itself only, overrides tech implied by magFileName +# -S if given, changes from techfile's default drc style (perhaps "drc(fast)") to named style, for example: -S "drc(full)" +# -l if given, enumerates EVERY individual error bbox to the FILE_NAME +# -N if given, do Not use -dereference option of load for topcell (not available in older magics) +# -F flatten top cell in-memory only, not saved (experimental) +# -P do crude drc performance measurement. At top-cell, do 'drc find' <N> times and report time per call. +# Stdout will log a pareto of error type by count regardless. +# +# <magFileName>: names a .mag file, the toplevel of the hier. to DRC/pareto +# +# Normal magic init. files are STILL sourced: ~/.magicrc and either $CWD/.magicrc or $CWD/magic_setup. +# (This would NOT happen if -rcfile magic cmd-line option were used). +# +# WARNING: Before 8.1.70, *.mag on cmd-line that was only found in cell search path set by .magicrc inits, +# would FAIL to determine the default tech-file. +# +# rb@ef 2015-06-30 author +# rb 2020-03-11 embed some library functions, to standalone from efabless-opengalaxy env, test via magic-8.2.194 +# +# magic itself outputs following usage message though -rcfile doesn't appear to work (in some versions): +# Usage: magic [-g gPort] [-d devType] [-m monType] [-i tabletPort] [-D] [-F objFile saveFile] +# [-T technology] [-rcfile startupFile | -norcfile][-noconsole] [-nowindow] [-wrapper] [file] +# +set Prog "magicDrc" + +set argv [eval "list $env(_M0)"] ;# orig. mix of native plus custom args, for logging all args to script + +proc usage {args} { + if {[llength $args] > 0} { + puts "ERROR: ${::Prog}: [join $args]" + } + puts {usage: [ -T <techfilePath> ] [-S <drcStyleName>] [-N] [-l FILE_NAME] <magFileName>} + puts " -T name specific techfile, passed to magic itself only, overrides tech implied by magFileName" + puts " -S if given, changes from techfile's default drc style (perhaps \"drc(fast)\") to named style, for example: -S \"drc(full)\"" + puts " -l if given, enumerates EVERY individual error bbox to the FILE_NAME" + puts " -N if given, do not use -dereference option of load for topcell (not available in older magics)" + puts " Stdout will log a pareto of error type by count regardless." + puts "" + puts " Recommend to run in dir with a ./.magicrc (or ./magic_setup) to configure magic's" + puts " cell search path, thru addpath statements, to locate all cells." +} + +# optionally hardcode library proc-s (part of site-wide extensions - always available - in context of efabless/open-galaxy) +# This is to make the script more standalone from efabless environment; but these capabilities should be native to magic. + +if {[info command scratchWritable] == {}} { + puts "${::Prog}: hardcoding library proc-s..." +# Replacement for 'cellname list exists CELLNAME', to fix ambiguity for cell "0". +# For cell "0" test for membership in 'cellname list allcells'. +# +# Instead of returning 0 for (non-existent) and cellname for exists, +# returns regular 0/1 instead for non-existent/exists. +# +# Therefore NOT direct replacement for uses of 'cellname list exists CELL'. +# Requires code changes. +proc cellnameExists {cell} { + expr {$cell ne "0" && [cellname list exists $cell] eq $cell || + $cell eq "0" && [lsearch -exact [cellname list allcells] $cell] > -1} +} + +# +# scratchWritable [-cleanup] [cellname1 ...] -- +# +# Turn readonly cells writable in-memory, via redirect to scratch dir. +# No cellname args: default is to process just all non-writable cells. +# Explicit cellname arguments: ARE scatchified EVEN if ALREADY writable. +# Limitation: Explicit named cell created in-mem, never saved, won't scratchify. +# If just -cleanup: default is to only do cleanup: don't scratchify +# any cells. +# +# -cleanup: Last scratch-dir, if any, and contents are deleted first. +# No restoring old filepath of cells, save after cleanup will fail. +# +# Caller strongly recommended to first do: 'select top cell; expand' +# to force whole hier. of a topcell to be loaded from disk into memory. +# +# This proc does not force expand cells. Before expanded, cells cannot be +# checked whether writable, and cannot have filepath changed. +# +# For batch DRC, for 'drc listall count', every cell in-memory must +# appear writable. This is the work-around (caller to 1st ensure +# hier. is loaded): Reset filepath of readonly cells to a scratch dir, +# make a dummy/empty .mag in scratch dir for each cell. Change cell's +# writeable flag. +# +# Skipped cells: +# In all cases, cells are skipped if +# 'cellname filepath' matches ::scratchWritableDir (already scratchified), +# This proc does NOT try and force expand; it presumes caller forced an expand +# thus cells are skipped if: +# 'cellname filepath' is "default" (can mean not expanded yet, or created never saved), +# 'cellname filepath' is <CELLNAME>.mag, indicates failed expand (unbound). +# Note: when filepath gives "default" or <CELLNAME>.mag, the writeable check not meaningful. +# +# How to scratchify all in-memory cells (still subject to internal skipping): +# scratchWritable {*}[cellname list allcells] +# +# TODO: use a combo of filepath & flags likely can detect created in-mem, +# and could redirect those too scratch dir if named explicitly. +# +# Side-effects: +# Runs zero or one subprocess, '/bin/mktemp -d' to make a scratch dir. +# Redirects where newly modified cells would be saved, if they ever are saved. +# Make's a scratch dir that needs to be cleaned-up. +# Leaves empty *.mag files in that scratch dir. +# +# Uses/requires proc cellnameExists. +# +# Same scratch-dir is reused if called multiple times, until next -cleanup. +# +# return value: list of cells not processed (skipped) for reasons cited above. +# Non-existent cells are also skipped but not included in the return list. +# +if {![info exists ::scratchWritableDir]} {set ::scratchWritableDir {}} +if {![info exists ::scratchWritableVerb]} {set ::scratchWritableVerb 0} +proc scratchWritable {args} { + # parse -cleanup option + set clean [expr {[lindex $args 0] eq {-cleanup}}] + if {$clean} { + set args [lrange $args 1 end] + } + + # If explicit cells given: don't limit to processing just readOnly cells. + set onlyReadonly [expr {$args == {}}] + + # only if no -cleanup, does empty cell list imply all cells + set allcell [cellname list allcells] + if {!$clean && $args == {}} { + set args $allcell + } + + # do cleanup + if {$clean} { + if {$::scratchWritableDir != {} && [file isdir $::scratchWritableDir]} { + set files [glob -dir $::scratchWritableDir -- {*.ext} {*.mag}] + lappend files $::scratchWritableDir + if {$::scratchWritableVerb} { + puts "scratchWritable: running, file delete $files" + } + eval {file delete} $files + set ::scratchWritableDir {} + } + } + + # Filter out non-existent or unbound cells. + # Optionally filter already writable cells. + # + # Unbounds result from placements of cells that now don't exist: + # fail to expand. This proc does not try and force expand; it + # presumes a forced expand was already done by caller (if caller + # wished). + # + # Referenced/used cells are initially unexpanded, not yet even located + # located in the search path, 'cellname filepath' returns "default". + # If expand fails (not found in search path), then 'cellname filepath' + # returns <CELLNAME>.mag, if expand worked, the directory containing + # the cell. + # + # If cell was 'cellname create' made, but never saved also "default". + # Such a cell is writable. So filter "default" and <CELLNAME>.mag. + set skipped {} + set ercell1 {} + set docells {} + foreach cell $args { + # filter (without recording as skipped) non-existent cells. + if {![cellnameExists $cell]} { continue } + + # filepath = "default": unexpanded (not loaded from disk), + # or created in-mem and never saved (is writable already + # though flags won't say so): skip both. + # TODO: use a combo of filepath & flags likely can detect created in-mem, + # and might be able to redirect them too to scratch dir if named explicitly. + set tmppath [cellname list filepath $cell] + if {$tmppath eq "default"} { + lappend skipped $cell + continue + } + + # flags not meaningful, until expanded or expand attempted. + # After expand attempt (filepath != "default"), and flags + # can now be used to determine cell unbound: not available. + set flags [cellname list flags $cell] + if {[lsearch -exact $flags available] < 0} { + lappend ercell1 $cell + continue + } + + if {$onlyReadonly && + [cellname list writeable $cell] eq "writeable"} { + lappend skipped $cell + continue + } + lappend docells $cell + } + + if {$::scratchWritableVerb} { + puts "scratchWritable: skipped cells: $skipped" + } + + # don't make a scratch dir if no work to do + if {$docells == {}} { + if {$::scratchWritableVerb} { + puts "scratchWritable: scratch-directed 0 cells" + } + return $skipped + } + + # make a scratch dir if needed + if {$::scratchWritableDir == {}} { + if {[catch {set dir [string trimright [exec /bin/mktemp -d]]} msg]} { + error "ERROR: scratchWritable, '/bin/mktemp -d' failed, $msg" + } + if {![file isdir $dir] || ![file writable $dir]} { + error "ERROR: scratchWritable, mktemp gave $dir, not a writable dir" + } + set ::scratchWritableDir $dir + } + + set ercell2 {} + set okcell {} + set madef 0 + foreach cell $docells { + # Relocate if needed: filepath doesn't already point to the scratch dir). + # 'cellname list filepath <cellNm>' -> appears to omit .mag extension, + # but disk-file needs the .mag in the path. + set trgr [file join $::scratchWritableDir "$cell"] ;# expected "lookup" path + set trgw [file join $::scratchWritableDir "$cell.mag"] ;# true "write" disk path + set src [cellname list filepath $cell] + if {[cellname list filepath $cell] ne $trgr && [cellname list filepath $cell] ne $trgw} { + + # make empty .mag for the cell + if {[catch {set outmag [open $trgw w]} msg]} { + lappend ercell2 $cell + continue + } + incr madef + close $outmag + + # relocate cell to new file + cellname list filepath $cell $::scratchWritableDir + } + + # make cell writable + cellname list writeable $cell true + lappend okcell $cell + } + + if {$::scratchWritableVerb} { + puts "scratchWritable: scratch-directed $madef cells" + } + if {$ercell1 != {} || $ercell2 != {}} { + set pre "ERROR: scratchWritable, " + set msg {} + if {$ercell1 != {}} { + lappend msg "$pre unbound cell(s): $ercell1" + } + if {$ercell2 != {}} { + lappend msg "$pre failed to make .mag for cell(s): $ercell2" + } + error [join $msg "\n"] + } + set skipped +} ;# end proc scratchWritable +} + +# without top-level proc around bulk of script, intermediate error statements don't abort script. +proc main {argv} { + +# process name-value pair options, if any +set nbrErr 0 +set ndx 0 +set max [llength $argv] +set extTechOpt {} ;# -T ... +set enumFilel {} ;# -l ... enum output file +set variant {} ;# -S ... non-default drc style +set flatten 0 +set perfN 0 ;# -P <N> do crude DRC perf. test +set noderef 0 ;# -N disable dereference option of: 'load ... -dereference' + +while {$ndx < $max && [string match "-*" [lindex $argv $ndx]]} { + set opt [lindex $argv $ndx] + incr ndx + switch -exact -- $opt { + -T { + if {$ndx == $max} { + usage "missing tech-file argument for -T option" + exit 1 + } + set extTechOpt [lindex $argv $ndx] + incr ndx + } + -S { + if {$ndx == $max} { + usage "missing drcStyle argument for -S option" + exit 1 + } + set variant [lindex $argv $ndx] + incr ndx + } + -P { + if {$ndx == $max} { + usage "missing count argument for -P option" + exit 1 + } + set perfN [lindex $argv $ndx] + incr ndx + } + -F { + set flatten 1 + } + -N { + set noderef 1 + } + -l { + if {$ndx == $max} { + usage "missing outputFile argument for -l option" + exit 1 + } + set enumFilel [lindex $argv $ndx] + incr ndx + if {[catch {set enumOut [open $enumFilel w]} msg]} { + error "ERROR: ${::Prog}: failed to open-for-write '$enumFilel' threw error, $msg" + } + puts "${::Prog}: enumerating each error bbox to: $enumFilel" + } + default { + usage "unknown option: $opt" + exit 1 + } + } +} + +if {$ndx == $max} { + usage "missing magFileName argument, the topcell" + exit 1 +} + +# get cmd-line topcell, minus dir-path; and minus extension IFF ext is .mag +set topc [file tail [lindex $argv $ndx]] ; incr ndx +if {[file extension $topc] eq ".mag"} { + set topc [file rootname $topc] +} +set topcStr $topc + +# abort if user supplies extra args. +if {$ndx != $max} { + usage "extra/unspported arg past magFileName, '[lindex $argv $ndx]'" + exit 1 +} + +# load the techfile +if {$extTechOpt != ""} { + if {![file readable $extTechOpt]} { + error "ERROR: ${::Prog}: tech-file \"$extTechOpt\" is not readable." + } + + tech load $extTechOpt + + # Verify the cmd-line -T option (if any) is still the current 'tech filename'. If we didn't + # explicitly 'tech load' ourselves, the .magicrc or magic.setup might 'tech load' something else. + # The 'file join [pwd] ...' makes relative path absolute, but without resolving + # all symlinks (which 'file normalize' would do). + set techf2 [file join [pwd] [tech filename]] + set techf1 [file join [pwd] $extTechOpt] + if {$techf1 != $techf2} { + error "ERROR: ${::Prog}: failed tech-load \"$techf1\" (tech-filename=\"$techf2\" not a match)" + } +} + +# if mag-cell were passed natively on magic cmd-line, this is too late: +if {$noderef} { + load $topc +} else { + load $topc -dereference +} + +# error checks: ensure (1st) cmd-line cellname now in-memory, and is now the current cell + +set topcells [cellname list top] +# filter (UNNAMED) +set topcells [lsearch -exact -not -all -inline $topcells "(UNNAMED)"] +# puts "cellname-list-top is: $topcells" + +# could use [cellname list flags $topc] and ensure non-null result (list with available), +# but if it fails (cell not found), it generates unwanted stdout. +if {[lsearch -exact [cellname list allcells] $topc] < 0} { + error "ERROR: ${::Prog}: cmd-line topcell \"$topc\" not in magic's list of allcells." +} + +if {[lsearch -exact $topcells $topc] < 0} { + puts "WARNING: ${::Prog}: cmd-line topcell \"$topc\" not in magic's list of topcells: $topcells" +} + +# crude way even in batch to determine the "current" cell; perhaps not yet the "Edit" cell +# WARNING, if topcell locked elsewhere or not writable, it can't become the "Edit" cell. +set topcw [cellname list window] +if {$topcw ne $topc} { + error "ERROR: ${::Prog}: cmd-line topcell, $topc, is not the current cell, 'cellname list window'=$topcw" +} + +# for topcell, filepath==default doesn't change by expand, +# indicates unknown cell created in-memory by magic's startup sequence. +if {[cellnameExists $topc] && + [cellname list filepath $topc] eq "default"} { + puts "Search path for cells is \"[path search]\"" + error "ERROR: ${::Prog}: cmd-line topcell, $topc, auto-created in-memory: not found in cell search path" +} + +if {$flatten} { + # delete (UNNAMED) if any. + set trg "(UNNAMED)" + if {[cellnameExists $trg]} {cellname delete $trg} + + # rename top cell to (UNNAMED) + cellname rename $topc $trg + + # now Edit Cell contents are original top cell, but under name (UNNAMED) + # flatten Edit-Cell into original top cell name + puts "${::Prog}: flattening..." + flatten $topc + + # load and edit new version of top cell. This is from in-memory, just making it current-cell. + # (So with or without -dereference is expected would have discernable effect by now; + # and since it's flattened there are no subcell instances either). + if {$noderef} { + load $topc + } else { + load $topc -dereference + } + + # crude way even in batch to determine the "current" cell; perhaps not yet the "Edit" cell + # WARNING, if topcell locked elsewhere or not writable, it can't become the "Edit" cell. + set topcw [cellname list window] + if {$topcw ne $topc} { + error "ERROR: ${::Prog}: assertion failed, post-flatten, $topc, is not the current cell, 'cellname list window'=$topcw" + } + + # should not be necessary: + select top cell + edit + + # crude way even in batch to determine the "current" cell; perhaps not yet the "Edit" cell + # WARNING, if topcell locked elsewhere or not writable, it can't become the "Edit" cell. + set topcw [cellname list window] + if {$topcw ne $topc} { + error "ERROR: ${::Prog}: assertion-2 failed, post-flatten, $topc, is not the current cell, 'cellname list window'=$topcw" + } +} + +# todo: Need a check for non-existent topcell (though magic reported not-found and auto-created it). +# todo: We should locate fullpath to topcell on disk to record this in the log. +# +# WARNING, magic junkCell, or magic junkDir/junkCell (passing paths to cells that don't exist), +# generate startup error messages (could not open cell), but magic creates the new cell in memory. +# No simple way to detect this after the fact. Can walk the cell search path to verify it's on disk. +# For the non-existent cell, magic also discards the dirpath from the cmd-line arg. +# If it did exist at that path, magic opens it successfully, despite that dir not in search path. +# A proper check for implicit create of non-existent cell should account for this effect too. + +# write a line with timestamp and all arguments to stdout (log) +# (magic renames the TCL clock command) +set clockp clock +if {[info command $clockp] == {} && [info command orig_clock] != {}} { + set clockp orig_clock +} +set nowSec [$clockp seconds] +set timestamp [$clockp format $nowSec -format "%Y-%m-%d.%T.%Z"] +# Show quoted logged argv here so it's machine readable for replay purposes. +puts "${::Prog}: timestamp: $timestamp, arguments: $::env(_M0)" + +puts "${::Prog}: running drc on topcell: $topcStr" +puts "${::Prog}: tech-name: [tech name] -version: [tech version] -filename: [tech filename] -lambda [tech lambda]" + +# log the cell search path for this run. Emulates format output by plain "path" (but which prints more than one the cell search path). +puts "Search path for cells is \"[path search]\"" + +set res {} +if {$variant != {}} { + if {[catch {set res [drc list style $variant]} msg]} { + puts "ERROR: ${::Prog}: but CONTINUING, 'drc style $variant' threw error, $msg" + } +} else { + if {[catch {set res [drc list style]} msg]} { + puts "ERROR: ${::Prog}: but CONTINUING, 'drc list style' threw error, $msg" + } +} +if {$res != {}} { + puts "drc style reports:\n$res" +} + +# just Manhattan is default, turn on euclidean, and log new mode +drc euclidean on +drc euclidean + +# 1st "select top cell": without it drc-list-count is blank, and error count reduced. +# May be unnecessary in some cases. +# WARNING: if topcell locked by another process, default box is NOT set to full top cell without this (as of 8.1.70 or earlier) +select top cell +# expand cell cells: scratchify step requires this up front else can't force all cells writable. +expand + +# The expand triggered load of all subcells. Till then allcells may be incomplete. +set allcells [cellname list allcells] +# filter (UNNAMED) +set allcells [lsearch -exact -not -all -inline $allcells "(UNNAMED)"] +set nbrAllCells [llength $allcells] +# puts "DEBUG: cellname-list-allcells are: $allcells" + +# TODO: do explicit separate unbound check here (don't rely on scratchWritable for this) + +# make allcells writable. Can error out: +# if are unbounds, or couldn't make scratch dir or .mag files. +set scratch [expr {!$flatten}] +if {$scratch && [catch {scratchWritable} msg]} { + puts stderr "ERROR: ${::Prog}: aborting at scratchWritable due error(s):" + error $msg +} + +# Erase all preexisting *.drtcl first. Else when cell transitions from +# dirty in previous run (leaving *.drtcl), to clean, the old *.drtcl +# remains. +# TODO: only delete *.drtcl of cells in 'cellname list allcells'? +# TODO: move this up, before scratchWritable? +set files [glob -nocomplain -types {f} -- ./*.drtcl] +if {$files != {}} { + # TODO: detect/report failure details better here? + puts "${::Prog}: deleting preexisting *.drtcl" + set msg {} + set delfail [catch {eval {file delete} $files} msg] + set files [glob -nocomplain -types {f} -- ./*.drtcl] + if {$delfail || $files != {}} { + puts "ERROR: ${::Prog}: failed to clean old ./*.drtcl files. $msg" + incr nbrErr + } +} + +edit ;# Fails if topcell not writable, should not be not needed post scratchWritable + +set outScale [cif scale out] + +# "select top cell" and box [view bbox] should be equivalent in +# placing a box around whole cell extent. +# The box cmd ALSO prints lambda and micron user-friendly box data, +# but it prints microns with not enough resolution, +# (and no option to disable that flawed print out). +# +# todo: emulate box output in full, except for higher resolution, +# here we only scale/print the overall bbox in microns. +# select top cell ;# paranoid, reset the box to data extents post-expand +# set bbox [view bbox] +# set bbs {} +# foreach oord $bbox { +# lappend bbs [format "%.3f" [expr {$outScale * $oord}]] +# } +# puts "outScale: $outScale, view-bbox: $bbox" +# puts "Root cell box2: ([lindex $bbs 0] [lindex $bbs 1]), ([lindex $bbs 2] [lindex $bbs 3])" + +# shouldn't need: +# drc on + +# Want to use 'drc list count' to tell us which cells have errors, so we can +# run 'drc listall why' on just those cells to enumerate details (which reruns +# drc again unfortunately). + +# For accurate DRC (as of 8.1.70), specifically 'drc list count', need: +# all-writable cells, then run: 'drc check' & 'drc catchup'. +# Now we have all writable cells. +set timeRepeat 1 +if {$perfN > 0} { + set timeRepeat $perfN +} +set timeres [time { + set drcCheckTime1 [time {drc check}] + set drcCheckTime2 [time {drc catchup}] } $timeRepeat] + +if {$perfN > 0} { + puts "perf: ${perfN}X 'drc check','drc catchup': $timeres" + puts "perf: last 'drc check' time: $drcCheckTime1" + puts "perf: last 'drc catchup' time: $drcCheckTime2" + drc statistics + drc rulestats +} + +# todo: this 2nd select was in GDS version, test if needed in mag version: +# 2nd select top cell needed else error count may be reduced (why? bbox does not change due to DRC) +select top cell +set outScale [cif scale out] +set bbox [view bbox] +set bbs {} +foreach oord $bbox { + lappend bbs [format "%.3f" [expr {$outScale * $oord}]] +} +puts "outScale(ostyle=[cif list ostyle]): $outScale, view-bbox: $bbox" +puts "Root cell box: ([lindex $bbs 0] [lindex $bbs 1]), ([lindex $bbs 2] [lindex $bbs 3])" +# print several native bbox representations: +box + +# listall vs list appear same as of 8.1.70 or earlier. +# warning: celllist order is not stable, not repeatable; run to run on same data. +# puts "DEBUG: (drc listall count total) is $drcListCountTot" +set celllist [drc listall count] +set celllist [lsearch -not -all -inline -index 0 -exact $celllist "(UNNAMED)"] +# puts "DEBUG: (drc listall count) is [drc listall count]" +set drcListCountTot [drc list count total] +set nbrErrCells [llength $celllist] + +# TODO: major problem: 'drc listall why' repeated an every cell, will do subcells +# multiple times, as many times as their depth in the hier. + +# canonicalize order of celllist, move topc to last (if present whatsoever). +# force our own artificial entry for topc (zero errors) if not present (was clean) +# puts "DEBUG: celllist before: $celllist" +set topcPair [lsearch -inline -index 0 -exact $celllist $topc] +set celllist [lsearch -not -all -inline -index 0 -exact $celllist $topc] +set celllist [lsort -index 0 -dictionary $celllist] +if {$topcPair == {}} { + # puts "DEBUG: $topc clean, forcing celllist entry for it" + set topcPair [list $topc 0] +} +lappend celllist $topcPair +# puts "DEBUG: celllist after: $celllist" +# puts "DEBUG: adjusted celllist(drc list count) is $celllist" + +# loop over celllist +set doFeedback 1 ;# TODO: add cmd-line option to control this + +# collect 'dry listall why' for the cells in 'cell list count' with non-zero errors +# If 'drc listall why' does report zero (shouldn't since we're only processing cells +# with non-zero counts), it unavoidably writes to console a No drc errors found message. +# We don't want such polluting our list of per-cell pareto's, so don't risk running +# drc why in-line, in-between per-cell paretos. +array set cell2why [list $topc {}] ;# default at least empty topcell why list +foreach pair $celllist { + if {[lindex $pair 1] < 1} {continue} ;# only happens for topcell if topcell clean + set acell [lindex $pair 0] + + # TODO: magic needs a useful error checkable load command. + # The 'load' writes errors to console/stdout, but never throws an error, + # nor gives a useful return value. i.e. These catch never catch. + if {$noderef} { + if {[catch {set res [load $acell]} msg]} { + puts "ERROR: ${::Prog}: 'load $acell' threw error, $msg" + exit 1 + } + } else { + if {[catch {set res [load $acell -dereference]} msg]} { + puts "ERROR: ${::Prog}: 'load $acell -dereference' threw error, $msg" + exit 1 + } + } + select top cell ;# paranoid, that without it, drc's are reduced + + # optionally do crude DRC perf. analysis here. Only for top-cell, only if -P <N> option given. + set timeRepeat 1 + if {$perfN > 0 && $topc eq $acell} { + set timeRepeat $perfN + } + set timeres [time {set cell2why($acell) [drc listall why]} $timeRepeat] + if {$perfN > 0 && $topc eq $acell} { + puts "perf: ${::Prog}: for '$acell', ${perfN}X 'drc listall why': $timeres" + } +} + +# done with all magic-specifics here. Shouldn't need scratch dir any longer. +# If this prints something (generally does), don't want it after the pareto table. + +# clean/remove the tmp scratch dir and contents +# TODO: all fatal errors need to call a cleanup proc that includes this before abort +if {$scratch && [catch {scratchWritable -cleanup} msg]} { + puts "ERROR: ${::Prog}: 'scratchWritable -cleanup' threw error, $msg" + incr nbrErr +} + +set gtotal 0 +set gcells 0 +foreach pair $celllist { + puts "" + set acell [lindex $pair 0] + if {![info exists cell2why($acell)]} { + puts "ERROR: ${::Prog}: cell: $acell, assertion failed, no drc-why list for 'drc list count' pair: $pair" + # exit 1 + continue + } + set whys $cell2why($acell) + + # enumerate errors under box, plain "drc why" only reports unique types, no quantities + # as-yet-undocumented "drc listall why" gives: {errStr1 {errBox1 ...} errStr2 {errBox1 ...} ... } + set pareto {} + set total 0 + set enumTotal 0 + set types 0 + set typeDup 0 + set dups 0 + + set fbOut {} + # file path for feedback, keep in CWD + if {$doFeedback && $fbOut == {}} { + set fbOut "./$acell.drtcl" + if {![file writable $fbOut] && + ([file exists $fbOut] || ![file writable [file dir $fbOut]])} { + puts stderr "ERROR: ${::Prog}: feedback output not writable, $fbOut" + incr nbrErr + set fbOut {} + } elseif {[catch {set outfb [open $fbOut w]} msg]} { + puts stderr "ERROR: ${::Prog}: failed to truncate previous feedback output, $fbOut : $msg" + incr nbrErr + set fbOut {} + } + } + foreach {str boxes} $whys { + # sort errors + set boxes [lsort -dictionary $boxes] + + # for our pareto, gather data + set this [llength $boxes] + incr total $this + incr types + lappend pareto [list $this $str] + + # for enumOut, emulate formatting of $CAD_ROOT/magic/tcl/drc.tcl, which is + # not tk pure: fails with complaint about winfo + # note: we walk these errors also in order to count/report stats on duplicates, even if not outputing enumerations + if {[info exists enumOut]} { + if {$types == 1} { + puts $enumOut "[join $pair]\n----------------------------------------" + } + puts $enumOut "${str}\n----------------------------------------" + } + set lastq {} + set thisDup 0 + foreach quad $boxes { + set quadUM {} + foreach coord $quad { + set valum [expr {$coord * $outScale}] + set valumf [format "%.3f" $valum] + lappend quadUM "${valumf}um" + } + set dup [expr {$quad == $lastq}] + incr thisDup $dup + set line $quadUM + if {[info exists enumOut]} { + if {$dup} { + puts $enumOut "[join $line] #dup" + } else { + puts $enumOut [join $line] + } + } + if {$fbOut != {}} { + set line [join $quadUM] + regsub -all -- "(\[\[\"\$\\\\])" $str {\\\1} strdq + puts $outfb "[concat box $line]" nonewline + puts $outfb " ; feedback add \"$strdq\" medium" nonewline + if {$dup} { + puts $outfb " ;#dup" + } else { + puts $outfb "" + } + } + + incr enumTotal + set lastq $quad + } + if {$thisDup} { + incr typeDup + incr dups $thisDup + } + if {[info exists enumOut]} { + puts $enumOut "----------------------------------------\n" + } + } + + if {$fbOut != {}} { + close $outfb + set outfb {} + } + + set pareto [lsort -integer -decreasing -index 0 $pareto] + if {$total > 0} { + puts "--- #err|description, table for cell: $acell" + } + foreach pair $pareto { + puts "[format {%8d} [lindex $pair 0]] [lindex $pair 1]" + } + if {$typeDup} { + puts "[format {%8d} $dups] total duplicate error(s) among $typeDup error type(s), cell: $acell" + } + puts "[format {%8d} $total] total error(s) among $types error type(s), cell: $acell" + # add to grand-totals + incr gcells + incr gtotal $total + + # always compare the total from the enum to the pareto as error check + if {$total != $enumTotal} { + puts "ERROR: ${::Prog}: cell: $acell, assertion failed, pareto vs enum count mismatch: $total != $enumTotal" + incr nbrErr + } +} + +# TODO: in the summary echo also techfile-full-path and drc-style name? +# grand totals +puts "[format {%8d} $nbrErrCells] of $nbrAllCells cell(s) report error(s)" +puts "[format {%8d} $gtotal] grand-total error(s) across $gcells cell(s)" + +# wish to compare the drc-list-count-total to the pareto total. +# Per te 2014-08-27 : it is not an error. +# if {$total != $drcListCountTot} { +# puts "info: ${::Prog}: drc-list-count-total vs drc-listall-why mismatch {drc list count total} gave $drcListCountTot, but {drc listall why} gave $total" +# } + +if {[info exists enumOut]} { + close $enumOut +} + +# set celllist4 [drc list count] +# puts "DEBUG: drc list count0: $celllist0" +# puts "DEBUG: drc list count1: $celllist1" +# puts "DEBUG: drc list count2: $celllist2" +# puts "DEBUG: drc list count3: $celllist3" +# puts "DEBUG: native (drc list count) is $celllistn" +# puts "DEBUG: drc list count4: $celllist4" + +# todo: implement super-pareto, ranked table of SUM of all DRC errs/counts from ALL cells. +# (It still would not reflect as-if-flat hierarchical expansion due to repetition of instances). + +set nbrErr +} + +# non-zero exit-status on errors, either if thrown by main, or counted and returned by main +set nbrErr 0 +if {[catch {set nbrErr [main $argv]} msg]} { + puts stderr $msg + set nbrErr 1 +} elseif {$nbrErr > 0} { + puts "ERROR: ${::Prog}: script terminated with errors reported above." +} +exit $nbrErr + +# for emacs syntax-mode: +# Local Variables: +# mode:tcl +# End:
diff --git a/utils/utils/magicGdrc b/utils/utils/magicGdrc new file mode 100755 index 0000000..88280ee --- /dev/null +++ b/utils/utils/magicGdrc
@@ -0,0 +1,911 @@ +#!/bin/sh +# SPDX-FileCopyrightText: 2014, 2015, 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# Copyright (C) 2014, 2015, 2020 efabless Corporation. All Rights Reserved. +# send a very-first -T FILE to magic's startup, hide all other args from magic-startup +# for-bash\ + export _M0= ;\ + for i in "$@" ; do _M0="$_M0${_M0:+ }\"${i//\"/\\\"}\""; done ;\ + case "$1" in -T) tch="$2"; shift; shift; _MARGS="$*" exec magic -dnull -noconsole -T "$tch" <"$0" ;; esac +# hide next line from magic(tclsh):\ +_MARGS="$*" exec magic -dnull -noconsole <"$0" +# +# magicDRC: run magic-DRC in batch on a GDS file, tabulate/pareto the error counts. +# +# rb@ef 2014-08-28 author +# rb 2020-02-19 embed some library functions, to standalone from efabless-opengalaxy env, test via magic-8.2.188 +# +# todo: support "-" as GDS file arg, to mean GDS from stdin +# + +set ::Prog "magicGdrc" +set argv [eval "list $env(_M0)"] ;# orig. mix of native plus custom args, for logging all args to script +# set argv [split $env(_MARGS)] ;# (currently unused) + +proc usage {args} { + if {[llength $args] > 0} { + puts "ERROR: ${::Prog}: [join $args]" + } + puts {usage: [ -T techfilePath ] [-S <drcStyleName>] [-I <cifIStyleName>] [-km FILE_NAME] [-l FILE_NAME] [-L FILE_NAME] gdsFileName [topCellName]} + puts " -T if given, must be very first" + puts " -S if given, changes from techfile's default/1st drc style (perhaps \"drc(fast)\") to named style, for example: -S \"drc(full)\"" + puts " -I if given, changes from techfile's default/1st cifinput style (perhaps \"vendorimport\" or \"import(exact)\") to named style, for example: -I \"import(magic)\"" + puts " -path-sub do 'gds path subcell yes' (default:no). Make unique subcell for each path: cut #tiles cost of angles." + puts " -poly-sub do 'gds polygon subcell yes' (default:no). Make unique subcell for each polygon: cut #tiles cost of angles." +# gds polygon subcell [yes|no] + puts " -pps Short hand, equivalent to giving both: -path-sub -poly-sub" + puts "" + puts " Error tabulation: By default (slowest, most detail): Report table of counts-by-errorString for all cells." + puts " Stdout logs a pareto of error-type by count unless disabled for some/all cells by below; topcell last." + puts " -tt Table of counts-by-errorString for ONLY topcell; and just lumped total error count per subcell." + puts " -tc Just lumped error counts per cell including topcell (fastest, least detail)." + puts " Cells NOT tabulating count-by-errorString can't appear in other output error files: feedback(*.drtcl), -l, -km." + puts " For lumped error counts, overlapped error shapes from unique error-types are merged further reducing count." + puts "" + puts " cell-type +-- (default) --+-- option -tt --+-- option -tc" + puts " subcell | count-by-errorString | lumped-error-count | lumped-error-count" + puts " topcell | count-by-errorString | count-by-errorString | lumped-error-count" + puts "" + puts " -km if given, write to FILE_NAME EVERY individual error bbox (MICRONS) in klayout Marker database(XML) format (suggest *.lyrdb)" + puts " -l if given, enumerates EVERY individual error bbox (MICRONS) to FILE_NAME, emulates $::CAD_ROOT/magic/tcl/drc.tcl" + puts " -L same as -l above, but outputs bbox-es in LAMBDA coordinates, not microns" + puts " -nf Do NOT write *.drtcl per-cell feedback files. Can be source-ed in magic and step thru: feedback find." + puts "" + puts " NOTES: Without explicit tech-file option: the ./.magicrc or ./magic_setup and ~/.magicrc may load a default tech-file." + puts " Therefore the tech-file used CAN depend on whether your CWD is ~/design/<CURRENT_DESIGN>/mag when running this script." + puts " Since no *.mag are loaded by this script: the cell search path defined by any init files has no impact." + puts " Since about 8.3.68, magic may generate error-type \"See error definition in the subcell\". There typically are" + puts " redundancies of errors across the hierarchy anyway (but with tech-file err-strings), this seems another form." + puts "" + puts "example, just list all styles: by causing an error which provokes usage report:" + puts " magicGdrc -T /ef/tech/XFAB/EFXH035B/libs.tech/magic/current/EFXH035B.tech" + puts "example, same but run in a ~/design/*/mag/ dir, so techfile set by ./.magicrc (else magic's builtin minimum.tech):" + puts " magicGdrc" + puts "example, run GDS drc, explicit: tech, cif-istyle, drc-style:" + puts " magicGdrc -T /ef/tech/SW/EFS8A/libs.tech/magic/current/EFS8A.tech -I vendorimport -S 'drc(full)' /tmp/mytop.gds mytopcell" + puts "example, run GDS drc, default tech & styles, write klayout marker database, no per-cell *.drtcl feedback files:" + puts " magicGdrc -km /tmp/mytop.lyrdb -nf /tmp/mytop.gds mytopcell" + puts "example, same but make subcells for paths & polygons" + puts " magicGdrc -km /tmp/mytop.lyrdb -nf -pps /tmp/mytop.gds mytopcell" + puts "example, run GDS drc, no feedback (*.drtcl), only lumped/merged err-count for all cells" + puts " magicGdrc -tc /tmp/mytop.gds mytopcell" + puts "example, run GDS drc, no feedback (*.drtcl), lumped/merged err-count for subcells, detail errors for topcell" + puts " magicGdrc -nf -tt /tmp/mytop.gds mytopcell" + puts "" + + reportTechFile + reportAllStyles + puts "" + + if {[llength $args] > 0} { + puts "ERROR: ${::Prog}: [join $args]" + } +} +proc gdsChk {file} { + foreach suffix {"" ".gds" ".gds2" ".strm"} { + if {[file readable "${file}${suffix}"]} {return 1} + } + puts "ERROR: ${::Prog}: Cannot open (as-is or with .gds, .gds2, or .strm) to read GDS-II stream from: $file" + exit 1 +} + +proc reportTechFile {} { + puts "${::Prog}: tech-name: [tech name] -version: [tech version] -filename: [tech filename] -lambda [tech lambda]" +} + +# query currently loaded tech-file for styles the user might need for -I -S options +# Suggest a bad tech-file if none are found or errors thrown. +# Used after finding error in -I -S options, and probably should add it to the usage. +proc reportAllStyles {} { + set errs {} + if {[catch {set allstyle [cif listall istyle]} msg]} { + lappend errs "ERROR: ${::Prog}: bad tech-file? failed to 'cif listall istyle', $msg" + } elseif {$allstyle == {}} { + lappend errs "ERROR: ${::Prog}: bad tech-file? no cifinput styles found by 'cif listall istyle'" + } else { + puts "info: ${::Prog}: cifinput styles available: $allstyle" + } + if {[catch {set allstyle [drc listall style]} msg]} { + lappend errs "ERROR: ${::Prog}: bad tech-file? failed to 'drc listall style', $msg" + } elseif {$allstyle == {}} { + lappend errs "ERROR: ${::Prog}: bad tech-file? no drc styles found by 'drc listall style'" + } else { + puts "info: ${::Prog}: drc styles available: $allstyle" + } + if {$errs != {}} { + + } + return [llength $errs] +} + +# optionally hardcode library proc-s (part of site-wide extensions - always available - in context of efabless/open-galaxy) +# This is to make the script more standalone from efabless environment; but these capabilities should be native to magic. + +if {[info command unbounds] == {}} { + puts "${::Prog}: hardcoding library proc-s..." +# Replacement for 'cellname list exists CELLNAME', to fix ambiguity for cell "0". +# For cell "0" test for membership in 'cellname list allcells'. +# +# Instead of returning 0 for (non-existent) and cellname for exists, +# returns regular 0/1 instead for non-existent/exists. +# +# Therefore NOT direct replacement for uses of 'cellname list exists CELL'. +# Requires code changes. +proc cellnameExists {cell} { + expr {$cell ne "0" && [cellname list exists $cell] eq $cell || + $cell eq "0" && [lsearch -exact [cellname list allcells] $cell] > -1} +} + +# Walk allcells to get/return list of cellNames that are unbound. +# Only use this after: 'select top cell; expand' to expand whole hierarchy. +# +# foreach CELL in 'cellname list allcells': +# if flags says available : it's Bound, goto next cell. +# if filepath is "default", try to expand the cell. +# if still "default"**: cell made by "cellname create", never saved, goto next. +# if filepath is CELL.mag, check for "available" flags, if none: Unbound. +# else cell is bound. +# **: should never get there +proc unbounds {} { + set allcells [cellname list allcells] + # filter (UNNAMED) + set allcells [lsearch -exact -not -all -inline $allcells "(UNNAMED)"] + # set nbrAllCells [llength $allcells] + set ercell {} + foreach cell $allcells { + # filter (without recording as skipped) non-existent cells. + if {![cellnameExists $cell]} { continue } + + # filepath = "default": unexpanded (not loaded from disk), + # or created in-mem and never saved (is writable already + # though flags won't say so): skip both. + # TODO: use a combo of filepath & flags likely can detect created in-mem + set tmppath [cellname list filepath $cell] + if {$tmppath eq "default"} { + lappend skipped $cell + continue + } + + # flags not meaningful, until expanded or expand attempted. + # After expand attempt (filepath != "default"), and flags + # can now be used to determine cell unbound: not available. + set flags [cellname list flags $cell] + if {[lsearch -exact $flags available] < 0} { + lappend ercell $cell + continue + } + } + set ercell ;# return list of unbound cells, if any +} +} + +# without top-level proc around bulk of script, intermediate error statements don't abort script. +proc main {argv} { + +set mlen [llength $argv] + +# process name-value pair options, if any +set nbrErr 0 +set ndx 0 +set max [llength $argv] +set extTechOpt {} ;# -T ... but not used here +set enumFilel {} ;# -l ... enum output file +set enumFileL {} ;# -L ... enum output file +set enumFileKm {} ;# -km ... enum output file +set variant {} ;# -S ... non-default drc style +set istyle {} ;# -I ... non-default cifinput style +set doFeedback 1 ;# -nf sets to 0: Do not write *.drtcl per-cell feedback files. +set pathSub 0 ;# -path-sub ... do 'gds path subcell yes' +set polySub 0 ;# -poly-sub ... do 'gds polygon subcell yes' +set subcellTab 1 ;# -tt, -tc both turn OFF subcell count-by-error report +set topcellTab 1 ;# -tc turns OFF topcell count-by-error report +set flatten 0 +while {$ndx < $max && [string match "-*" [lindex $argv $ndx]]} { + set opt [lindex $argv $ndx] + incr ndx + switch -exact -- $opt { + -T { + if {$ndx != 1} { + usage "-T option must very 1st (here was #$ndx)" + exit 1 + } + if {$ndx == $max} { + usage "missing tech-file argument for -T option" + exit 1 + } + set extTechOpt [lindex $argv $ndx] ;# unused + incr ndx + } + -S { + if {$ndx == $max} { + usage "missing drcStyle argument for -S option" + exit 1 + } + set variant [lindex $argv $ndx] + incr ndx + } + -I { + if {$ndx == $max} { + usage "missing cifinput-style argument for -I option" + exit 1 + } + set istyle [lindex $argv $ndx] + incr ndx + } + -F { set flatten 1} + -nf { set doFeedback 0 } + -path-sub { set pathSub 1} + -poly-sub { set polySub 1} + -pps { set pathSub 1; set polySub 1} + -tt { set subcellTab 0 ; set topcellTab 1} + -tc { set subcellTab 0 ; set topcellTab 0 } + -km { + if {$ndx == $max} { + usage "missing outputFile argument for -km option" + exit 1 + } + set enumFileKm [lindex $argv $ndx] + incr ndx + } + -l { + if {$ndx == $max} { + usage "missing outputFile argument for -l option" + exit 1 + } + set enumFilel [lindex $argv $ndx] + incr ndx + if {[catch {set enumOut [open $enumFilel w]} msg]} { + error "ERROR: ${::Prog}: failed to open-for-write '$enumFilel' threw error, $msg" + } + puts "${::Prog}: enumerating each error bbox to: $enumFilel" + } + -L { + if {$ndx == $max} { + usage "missing outputFile argument for -L option" + exit 1 + } + set enumFileL [lindex $argv $ndx] + incr ndx + if {[catch {set enumOutL [open $enumFileL w]} msg]} { + error "ERROR: ${::Prog}: failed to open-for-write '$enumFileL' threw error, $msg" + } + puts "${::Prog}: enumerating each error bbox to: $enumFileL" + } + default { + usage "unknown option: $opt" + exit 1 + } + } +} + +if {$ndx == $max} { + usage {Insufficient number of arguments, need gdsFileName [topCellName]} + exit 1 +} + +set gdsf [lindex $argv $ndx] ; incr ndx +set topc {} +set topcStr "(AUTO)" +if {$ndx < $max} { + set topc [lindex $argv $ndx] ; incr ndx + set topcStr $topc +} +# error if extra options (not understood, something is wrong): +if {$ndx < $max} { + error "ERROR: ${::Prog}: after gdsFile=\"$gdsf\", topcell=\"$topc\" found unsupported extra arguments: [lrange $argv $ndx end]" +} +# ndx no longer used for argv position from here + +gdsChk $gdsf + +# warning on combo of -tc & -km. If -km ok, open its output file. +if {$enumFileKm ne {}} { + if {! $topcellTab} { + puts "WARNING: ${::Prog}: with -tc cannot (-km) write klayout-marker-db" + } else { + if {[catch {set enumOutKm [open $enumFileKm w]} msg]} { + error "ERROR: ${::Prog}: failed to open-for-write '$enumFileKm' threw error, $msg" + } + puts "${::Prog}: enumerating each error bbox to: $enumFileKm" + } +} + +# write a line with timestamp and all arguments to stdout (log) +# (magic renames the TCL clock command) +set clockp clock +if {[info command $clockp] == {} && [info command orig_clock] != {}} { + set clockp orig_clock +} +set nowSec [$clockp seconds] +set timestamp [$clockp format $nowSec -format "%Y-%m-%d.%T.%Z"] +# TODO: quote logged argv here as needed so it's machine readable for replay purposes. +puts "${::Prog}: timestamp: $timestamp, arguments: $argv" + +# just Manhattan is default, turn on euclidean, and log new mode +drc euclidean on +drc euclidean + +# 8.1.83 this worked: +# drc off; gds drccheck no; gds read ... ; load topcell; select top cell; expand; drc check; drc update; drc listall count +# By 8.2.64, that fails, the 'drc listall count' reports errors only in the top-cell, no subcells. +# 8.1.83 & 8.2.193 this works (gds drccheck defaults to on anyway): +# drc off; gds drccheck yes; gds read ... ; load topcell; select top cell; expand; drc check; drc update; drc listall count +# +# But are we properly avoiding redundant drc runs? +# +# turn off background checker. We'll invoke checks explicitly. +drc off +gds drccheck yes +puts "drc status (whether background checking enabled) is: [drc status]" +puts "gds drccheck (whether gds-read marks new cells as need-drc) is: [gds drccheck]" + +# set user's drc style; set user's cifinput istyle +# These are back-to-back without intervening status messages. +# If both wrong their errors are back-to-back. +set res {} +set res [drc list style] +if {$variant != {}} { + set allstyle [drc listall style] + set ndx [lsearch -exact $allstyle $variant] + if {$ndx < 0} { + puts "ERROR: ${::Prog}: drc style '$variant' not one of those available: $allstyle" + incr nbrErr + } else { + set res [drc list style $variant] + } +} +set res2 [cif list istyle] +if {$istyle != {}} { + set allstyle [cif listall istyle] + set ndx [lsearch -exact $allstyle $istyle] + if {$ndx < 0} { + puts "ERROR: ${::Prog}: istyle '$istyle' not one of those available: $allstyle" + incr nbrErr + } else { + set res2 [cif istyle $istyle] + } +} +if {$res != {}} { + puts "drc style reports:\n$res" +} +if {$res2 != {}} { + puts "cif istyle reports:\n$res2" +} + +# gds {path,polygon} subcell yes +if {$pathSub != 0} { gds path subcells yes } +puts "gds path subcells: [gds path subcells]" +if {$polySub != 0} { gds polygon subcells yes } +puts "gds polygon subcells: [gds polygon subcells]" + +# todo: this catch never happens. Need nicer error check of 'gds read' somehow. Can check for zero-sized file? +# if use /dev/null for example, it prints its own error message, but no throw, no useful return value. +puts "doing: gds read $gdsf ..." +if {[catch {set res [gds read $gdsf]} msg]} { + puts "ERROR: ${::Prog}: 'gds read $gdsf' threw error, $msg" + incr nbrErr +} +# nothing useful: +# puts "gds-read res: $res" + +set topcells [cellname list top] +set allcells [cellname list allcells] +# puts "cellname-list-top from GDS is: $topcells" +# puts "cellname-list-allcells from GDS are: $allcells" +# filter (UNNAMED) +set topcells [lsearch -exact -not -all -inline $topcells "(UNNAMED)"] +set allcells [lsearch -exact -not -all -inline $allcells "(UNNAMED)"] +set nbrAllCells [llength $allcells] + +if {$topcells == {}} { + puts "ERROR: ${::Prog}: GDS-read did not report any useful cell name(s) found." + incr nbrErr +} + +if {$nbrErr > 0} { + return $nbrErr ;# outside of main, we print termination with errors message +} + +if {$topc == {}} { + # try and infer topcell from cellname-list-top. + # presume its list of cells not placed anywhere else. + # todo: test with "library" GDS having more than one topcell + # here we just take the last entry + set topc [lindex $topcells end] + set topcStr $topc + puts "WARNING: auto-picked top-cell \"$topc\"; the topcells inferred from GDS are: $topcells" +} else { + # verify input topc argument exists in GDS read result + set ndx [lsearch -exact $allcells $topc] + if {$ndx < 0} { + puts "ERROR: ${::Prog}: top-cell name: $topc, not found in GDS" + puts "info: top cells inferred from GDS are: $topcells" + puts "info: all cells inferred from GDS are: $allcells" + return [incr nbrErr] ;# outside of main, we print termination with errors message + } +} + +puts "${::Prog}: running drc on -gds: $gdsf -topcell: $topcStr" +reportTechFile + +# todo: need to error check load command somehow (no useful return value). +# it can fail with error message (in log) like: +# File dne.mag couldn't be found +# Creating new cell +if {[catch {set res [load $topc]} msg]} { + puts "ERROR: ${::Prog}: 'load $topc' threw error (maybe cellName not found in GDS?), $msg" + return [incr nbrErr] ;# outside of main, we print termination with errors message +} +# nothing useful: +# puts "load $topc res: $res" + +if {$flatten} { + # delete (UNNAMED) if any. + set trg "(UNNAMED)" + if {[cellnameExists $trg]} {cellname delete $trg} + + # rename top cell to (UNNAMED) + cellname rename $topc $trg + + # now Edit Cell contents are original top cell, but under name (UNNAMED) + # flatten Edit-Cell into original top cell name + puts "${::Prog}: flattening..." + flatten $topc + + # load and edit new version of top cell + load $topc + + # crude way even in batch to determine the "current" cell; perhaps not yet the "Edit" cell + # WARNING, if topcell locked elsewhere or not writable, it can't become the "Edit" cell. + set topcw [cellname list window] + if {$topcw ne $topc} { + puts "ERROR: ${::Prog}: assertion failed, post-flatten, $topc, is not the current cell, 'cellname list window'=$topcw" + return [incr nbrErr] ;# outside of main, we print termination with errors message + } + + # should not be necessary: + select top cell + edit + + # crude way even in batch to determine the "current" cell; perhaps not yet the "Edit" cell + # WARNING, if topcell locked elsewhere or not writable, it can't become the "Edit" cell. + set topcw [cellname list window] + if {$topcw ne $topc} { + puts "ERROR: ${::Prog}: assertion-2 failed, post-flatten, $topc, is not the current cell, 'cellname list window'=$topcw" + return [incr nbrErr] ;# outside of main, we print termination with errors message + } +} + +# Erase all preexisting *.drtcl first. Else when cell transitions from +# dirty in previous run (leaving *.drtcl), to clean, the old *.drtcl +# remains. +# TODO: only delete *.drtcl of cells in 'cellname list allcells'? +if {$doFeedback} { + set files [glob -nocomplain -types {f} -- ./*.drtcl] + if {$flatten} { + # only delete topcell's .drtcl in flatten mode, if there is one + set files [lsearch -all -inline -exact $files ./$topc.drtcl] + } + if {$files != {}} { + # TODO: detect/report failure details better here? + puts "${::Prog}: deleting preexisting *.drtcl" + set msg {} + set delfail [catch {eval {file delete} $files} msg] + set files [glob -nocomplain -types {f} -- ./*.drtcl] + if {$delfail || $files != {}} { + puts "ERROR: ${::Prog}: failed to clean old ./*.drtcl files. $msg" + incr nbrErr + } + } +} + +# 1st "select top cell": without it drc-list-count is blank, and error count reduced. +select top cell + +set bbox0 [view bbox] +set outScale [cif scale out] + +# set bbox1 [view bbox] + +# "select top cell" and box [view bbox] should be equivalent in +# placing a box around whole cell extent. +# The box cmd ALSO prints lambda and micron user-friendly box data, +# but it prints microns with not enough resolution, +# (and no option to disable that flawed print out). +# +# todo: emulate box output in full, except for higher resolution, +# here we only scale/print the overall bbox in microns. +set bbs {} +foreach oord $bbox0 { + lappend bbs [format "%.3f" [expr {$outScale * $oord}]] +} +puts "info: outScale: [format "%.6f" $outScale], view-bbox: $bbox0" +puts "info: Root cell box: ([lindex $bbs 0] [lindex $bbs 1]), ([lindex $bbs 2] [lindex $bbs 3])" + +drc check +drc catchup +drc statistics +drc rulestats +# puts "doing plain: drc count" +drc count + +# 2nd select top cell needed else error count may be reduced (why? bbox does not change due to DRC) +select top cell + +set celllist [drc listall count] +set drcListCountTot [drc list count total] +# puts stdout "(drc listall count) is << " nonewline; puts stdout [list $celllist] nonewline; puts " >>" +# puts stdout "(drc list count) is << " nonewline; puts stdout [list [drc list count]] nonewline; puts " >>" +# puts stdout "(drc list count total) is << " nonewline; puts stdout [list $drcListCountTot] nonewline; puts " >>" +# puts stdout "(drc listall count total) is << " nonewline; puts stdout [list [drc listall count total]] nonewline; puts " >>" +# puts stdout "(drc list why) is << " nonewline; puts stdout [list [drc list why]] nonewline; puts " >>" +# puts stdout "(drc listall why) is << " nonewline; puts stdout [list [drc listall why]] nonewline; puts " >>" + +set bbox2 [view bbox] +if {$bbox2 != $bbox0} { + set bbs {} + foreach oord $bbox2 { + lappend bbs [format "%.3f" [expr {$outScale * $oord}]] + } + puts "info: outScale: [format "%.6f" $outScale], view-bbox: $bbox2" + puts "info: Root cell box2: ([lindex $bbs 0] [lindex $bbs 1]), ([lindex $bbs 2] [lindex $bbs 3])" +} + + +# canonicalize order of celllist, move topc to last (if present whatsoever). +# force our own artificial entry for topc (zero errors) if not present (was clean) +# puts "celllist before: $celllist" +set nbrErrCells [llength $celllist] +set topcPair [lsearch -inline -index 0 -exact $celllist $topc] +set celllist [lsearch -not -all -inline -index 0 -exact $celllist $topc] +set celllist [lsort -index 0 -dictionary $celllist] +if {$topcPair == {}} { + # puts "info: ${::Prog}: $topc clean, forcing celllist entry for it" + set topcPair [list $topc 0] +} +lappend celllist $topcPair +# puts stdout "adjusted celllist(drc list count) is << " nonewline; puts stdout $celllist nonewline; puts " >>" + +array set kmErr2catNm {} +array set kmErr2catDesc {} +array set kmCell2item {} +if {$celllist != {} && [info exists enumOutKm]} { + # Header example of .lyrdb klayout Marker format + # <?xml version="1.0" encoding="utf-8"?> + # <report-database> + # <description>Diff of 'x.gds, Cell RINGO' vs. 'x.gds[1], Cell INV2'</description> + # <original-file/> + # <generator/> + # <top-cell>RINGO</top-cell> + # <tags> + # <tag> + # <name>red</name> + # <description>Red flag</description> + # </tag> + # ... + # </tags> + + puts $enumOutKm {<?xml version="1.0" encoding="utf-8"?><report-database>} + puts $enumOutKm "<description>$topc DRC timestamp: $timestamp, arguments: $argv</description>" + puts $enumOutKm {<original-file/><generator/>} + puts $enumOutKm "<top-cell>$topc</top-cell>" + puts $enumOutKm {<tags/>} + puts $enumOutKm {<cells>} + + # multiple <cells>...</cells> sections do accumulate, but cells and categories need + # to be defined before use in an item (specific error), and we know cell names here, + # so declare all cells to klayout here. + # + # Cell-specific header of klayout marker file + # <cell> + # <name>CELLNAME1</name> + # <variant>1</variant> (don't need) + # </cell> + # + foreach pair $celllist { + set acell [lindex $pair 0] + + # for -tt, no subcell error-detail: don't write subcells in <cells>...</cells> section. + if {$acell ne $topc && ! $subcellTab} { continue } + + puts $enumOutKm " <cell><name>$acell</name></cell>" + set kmCell2item($acell) {} + } + puts $enumOutKm {</cells>} +} + +# loop over celllist +set gtotal 0 +set gcells 0 +set lumpedHeader 0 +foreach pair $celllist { + set acell [lindex $pair 0] + set acount [lindex $pair 1] + + if {$acell ne $topc && ! $subcellTab} { + if {! $lumpedHeader} { + puts "--- #err|cell, lumped total counts" + set lumpedHeader 1 + } + puts "[format {%8d} $acount] $acell" + incr gcells + incr gtotal $acount + continue + } + if {$acell eq $topc && ! $topcellTab} { + if {! $lumpedHeader} { + puts "--- #err|cell, lumped total counts" + set lumpedHeader 1 + } + puts "[format {%8d} $acount] $acell" + incr gcells + incr gtotal $acount + continue + } + puts "" + + # todo: need useful error check of load command + if {[catch {set res [load $acell]} msg]} { + puts "ERROR: ${::Prog}: 'load $acell' threw error, $msg" + return [incr nbrErr] ;# outside of main, we print termination with errors message + } + + # instead use quiet version for per-cell selects + select top cell + + set drcListCountTot [drc listall count total] + + # enumerate errors under box, plain "drc why" only reports unique types, no quantities + # as-yet-undocumented "drc listall why" will give: {errStr1 {errBox1 ...} errStr2 {errBox1 ...} ... } + set pareto {} + set total 0 + set enumTotal 0 + set types 0 + set typeDup 0 + set dups 0 + + set fbOut {} + if {$acount != 0} { + # file path for feedback, keep in CWD + if {$doFeedback && $fbOut == {}} { + set fbOut "./$acell.drtcl" + if {![file writable $fbOut] && + ([file exists $fbOut] || ![file writable [file dir $fbOut]])} { + puts stderr "ERROR: ${::Prog}: feedback output not writable, $fbOut" + incr nbrErr + set fbOut {} + } elseif {[catch {set outfb [open $fbOut w]} msg]} { + puts stderr "ERROR: ${::Prog}: failed to truncate previous feedback output, $fbOut : $msg" + incr nbrErr + set fbOut {} + } + } + + foreach {str boxes} [drc listall why] { + # sort errors + set boxes [lsort -dictionary $boxes] + # for our pareto, gather data + set this [llength $boxes] + incr total $this + incr types + lappend pareto [list $this $str] + + # for enumOut, emulate formatting of $CAD_ROOT/magic/tcl/drc.tcl, which is + # not tk pure: fails with complaint about winfo + # note: we walk these errors also in order to count/report stats on duplicates, even if not outputing enumerations + if {[info exists enumOut]} { + if {$types == 1} { + puts $enumOut "[join $pair]\n----------------------------------------" + } + puts $enumOut "${str}\n----------------------------------------" + } + if {[info exists enumOutL]} { + if {$types == 1} { + puts $enumOutL "[join $pair]\n----------------------------------------" + } + puts $enumOutL "${str}\n----------------------------------------" + } + if {[info exists enumOutKm]} { + # category names must be declared all together up front before use in items + # so we only store their names (error strings) and error detail (items) + # to dump after all cells and errors are processed. + # TODO: Only quote catName in item if embeds dot, instead of full-time + # TODO: test klayout handles literal (non-entity) single-quote in double-quoted name + set strKmNm $str + set strKmDesc $str + regsub -all -- {&} $strKmDesc {\&} strKmDesc ;# perhaps not needed; just in case + regsub -all -- {<} $strKmDesc {\<} strKmDesc ;# description does not have such bug, so use correct entity + regsub -all -- {>} $strKmDesc {\>} strKmDesc ;# perhaps not needed; just in case + regsub -all -- {&} $strKmNm {-and-} strKmNm ;# perhaps not needed; just in case + regsub -all -- {>} $strKmNm {-gt-} strKmNm ;# perhaps not needed; just in case + regsub -all -- {<} $strKmNm {-lt-} strKmNm ;# catName klayout bug: info win truncates at '<' as < entity + regsub -all -- "\"" $strKmNm {'} strKmNm ;# we dqoute each catNm in item, so change embedded double to single + set kmErr2catNm($str) $strKmNm + set kmErr2catDesc($str) $strKmDesc + # + # example klayout Marker format, header of one item (one error instance) + # <item> + # <tags/> (don't need?) + # <image/> (don't need?) + # <category>'DRC-MSG-STR'</category> (cat1.cat2 path delimit by dot: names with dot need single|double quotes) + # <cell>RINGO:1</cell> (don't need :N variant suffix) + # <visited>false</visited> (optional? start with false?) + # <multiplicity>1</multiplicity> (not boolean, if error "represents" more that are NOT enumerated) + # <values> ... </values> + # </item> + + set itemStr "<item><category>\"$strKmNm\"</category><cell>$acell</cell><values>" + } + set lastq {} + set thisDup 0 + foreach quad $boxes { + set quadUM {} + set kmBoxUM {} + foreach coord $quad { + set valum [expr {$coord * $outScale}] + set valumf [format "%.3f" $valum] + lappend quadUM "${valumf}um" + lappend kmBoxUM ${valumf} + } + set dup [expr {$quad == $lastq}] + incr thisDup $dup + set line $quadUM + if {[info exists enumOut]} { + if {$dup} { + puts $enumOut "[join $line] #dup" + } else { + puts $enumOut [join $line] + } + } + if {[info exists enumOutL]} { + if {$dup} { + puts $enumOutL "$quad #dup" + } else { + puts $enumOutL $quad + } + } + if {[info exists enumOutKm]} { + # <value>text: 'item: polygon'</value> (text is optional? Repeat the box coordinates here in um?) + # <value>polygon: (1.4,1.8;-1.4,1.8;-1.4,3.8;1.4,3.8)</value> + # <value>box: (1.4,1.8;-1.4,3.8)</value> + # </values> + set kmItem $itemStr + append kmItem " <value>box: ([lindex $kmBoxUM 0],[lindex $kmBoxUM 1];[lindex $kmBoxUM 2],[lindex $kmBoxUM 3])</value>" + if {$dup} { + append kmItem " <value>text: 'dup'</value>" + } + append kmItem " </values></item>" + lappend kmCell2item($acell) $kmItem + } + if {$fbOut != {}} { + set line [join $quadUM] + regsub -all -- "(\[\[\"\$\\\\])" $str {\\\1} strdq + puts $outfb "[concat box $line]" nonewline + puts $outfb " ; feedback add \"$strdq\" medium" nonewline + if {$dup} { + puts $outfb " ;#dup" + } else { + puts $outfb "" + } + } + + incr enumTotal + set lastq $quad + } + if {$thisDup} { + incr typeDup + incr dups $thisDup + } + if {[info exists enumOut]} { + puts $enumOut "----------------------------------------\n" + } + if {[info exists enumOutL]} { + puts $enumOutL "----------------------------------------\n" + } + } + } + + if {$fbOut != {}} { + close $outfb + set outfb {} + } + + set pareto [lsort -integer -decreasing -index 0 $pareto] + if {$total > 0} { + puts "--- #err|description, table for cell: $acell" + } + foreach pair $pareto { + puts "[format {%8d} [lindex $pair 0]] [lindex $pair 1]" + } + if {$typeDup} { + puts "[format {%8d} $dups] total duplicate error(s) among $typeDup error type(s), cell: $acell" + } + puts "[format {%8d} $total] total error(s) among $types error type(s), cell: $acell" + # add to grand-totals + incr gcells + incr gtotal $total + + # always compare the total from the enum to the pareto as error check + if {$total != $enumTotal} { + puts "ERROR: ${::Prog}: cell: $acell, internal error, pareto vs enum count mismatch: $total != $enumTotal" + incr nbrErr + } + # wish to compare the drc-list-count-total to the pareto total. + # Per te 2014-08-27 : it is not an error. + if {$total != $drcListCountTot} { + # puts "info: ${::Prog}: cell: $acell, drc-list-count-total vs drc-listall-why mismatch {drc list count total} gave $drcListCountTot, but {drc listall why} gave $total" + } +} + +# grand totals +puts "[format {%8d} $nbrErrCells] of $nbrAllCells cell(s) report error(s)" +puts "[format {%8d} $gtotal] grand-total error(s) across $gcells cell(s)" + +if {[info exists enumOut]} { + close $enumOut +} +if {[info exists enumOutL]} { + close $enumOutL +} +if {[info exists enumOutKm]} { + # declare all category names and descriptions, note '<' in name vs description are represented differently + # + # <categories><category><name>layerN width -lt- 1.0um</name> + # <description>layerN width < 1.0um</description></category> + # <category> ... </category></categories> + # + puts $enumOutKm "<categories>" + foreach errStr [array names kmErr2catNm] { + set nm $kmErr2catNm($errStr) + set desc $kmErr2catDesc($errStr) + puts $enumOutKm " <category><name>$nm</name><description>$desc</description></category>" + } + puts $enumOutKm "</categories>" + + # dump all items (after all cells and all categories have been defined up front) + puts $enumOutKm "<items>" + foreach {acell items} [array get kmCell2item] { + foreach item $items { + puts $enumOutKm $item + } + } + puts $enumOutKm "</items>" + + # footer example .lyrdb klayout Marker file + # </report-database> + puts $enumOutKm {</report-database>} + close $enumOutKm +} +# todo: implement super-pareto, ranked table of SUM of all DRC errs/counts from ALL cells. +# (It still would not reflect as-if-flat hierarchical expansion due to repetition of instances). + +set nbrErr ;# return value +} ;# end main + +# non-zero exit-status on errors, either if thrown by main, or counted and returned by main +set nbrErr 0 +if {[catch {set nbrErr [main $argv]} msg]} { + puts stderr $msg + set nbrErr 1 +} elseif {$nbrErr > 0} { + puts "ERROR: ${::Prog}: script terminated with errors reported above." +} +exit $nbrErr + +# for emacs syntax-mode: +# Local Variables: +# mode:tcl +# End:
diff --git a/verilog/dv/caravel/caravel/defs.h b/verilog/dv/caravel/caravel/defs.h new file mode 100644 index 0000000..6e42c7a --- /dev/null +++ b/verilog/dv/caravel/caravel/defs.h
@@ -0,0 +1,203 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _STRIVE_H_ +#define _STRIVE_H_ + +#include <stdint.h> +#include <stdbool.h> + +// a pointer to this is a null pointer, but the compiler does not +// know that because "sram" is a linker symbol from sections.lds. +extern uint32_t sram; + +// Pointer to firmware flash routines +extern uint32_t flashio_worker_begin; +extern uint32_t flashio_worker_end; + +// Storage area (MGMT: 0x0100_0000, User: 0x0200_0000) +#define reg_rw_block0 (*(volatile uint32_t*)0x01000000) +#define reg_rw_block1 (*(volatile uint32_t*)0x01100000) +#define reg_ro_block0 (*(volatile uint32_t*)0x02000000) + +// UART (0x2000_0000) +#define reg_uart_clkdiv (*(volatile uint32_t*)0x20000000) +#define reg_uart_data (*(volatile uint32_t*)0x20000004) +#define reg_uart_enable (*(volatile uint32_t*)0x20000008) + +// GPIO (0x2100_0000) +#define reg_gpio_data (*(volatile uint32_t*)0x21000000) +#define reg_gpio_ena (*(volatile uint32_t*)0x21000004) +#define reg_gpio_pu (*(volatile uint32_t*)0x21000008) +#define reg_gpio_pd (*(volatile uint32_t*)0x2100000c) + +// Logic Analyzer (0x2200_0000) +#define reg_la0_data (*(volatile uint32_t*)0x25000000) +#define reg_la1_data (*(volatile uint32_t*)0x25000004) +#define reg_la2_data (*(volatile uint32_t*)0x25000008) +#define reg_la3_data (*(volatile uint32_t*)0x2500000c) + +#define reg_la0_ena (*(volatile uint32_t*)0x25000010) +#define reg_la1_ena (*(volatile uint32_t*)0x25000014) +#define reg_la2_ena (*(volatile uint32_t*)0x25000018) +#define reg_la3_ena (*(volatile uint32_t*)0x2500001c) + +// User Project Control (0x2300_0000) +#define reg_mprj_xfer (*(volatile uint32_t*)0x26000000) +#define reg_mprj_pwr (*(volatile uint32_t*)0x26000004) +#define reg_mprj_datal (*(volatile uint32_t*)0x26000008) +#define reg_mprj_datah (*(volatile uint32_t*)0x2600000c) + +#define reg_mprj_io_0 (*(volatile uint32_t*)0x26000020) +#define reg_mprj_io_1 (*(volatile uint32_t*)0x26000024) +#define reg_mprj_io_2 (*(volatile uint32_t*)0x26000028) +#define reg_mprj_io_3 (*(volatile uint32_t*)0x2600002c) +#define reg_mprj_io_4 (*(volatile uint32_t*)0x26000030) +#define reg_mprj_io_5 (*(volatile uint32_t*)0x26000034) +#define reg_mprj_io_6 (*(volatile uint32_t*)0x26000038) + +#define reg_mprj_io_7 (*(volatile uint32_t*)0x2600003c) +#define reg_mprj_io_8 (*(volatile uint32_t*)0x26000040) +#define reg_mprj_io_9 (*(volatile uint32_t*)0x26000044) +#define reg_mprj_io_10 (*(volatile uint32_t*)0x26000048) + +#define reg_mprj_io_11 (*(volatile uint32_t*)0x2600004c) +#define reg_mprj_io_12 (*(volatile uint32_t*)0x26000050) +#define reg_mprj_io_13 (*(volatile uint32_t*)0x26000054) +#define reg_mprj_io_14 (*(volatile uint32_t*)0x26000058) + +#define reg_mprj_io_15 (*(volatile uint32_t*)0x2600005c) +#define reg_mprj_io_16 (*(volatile uint32_t*)0x26000060) +#define reg_mprj_io_17 (*(volatile uint32_t*)0x26000064) +#define reg_mprj_io_18 (*(volatile uint32_t*)0x26000068) + +#define reg_mprj_io_19 (*(volatile uint32_t*)0x2600006c) +#define reg_mprj_io_20 (*(volatile uint32_t*)0x26000070) +#define reg_mprj_io_21 (*(volatile uint32_t*)0x26000074) +#define reg_mprj_io_22 (*(volatile uint32_t*)0x26000078) + +#define reg_mprj_io_23 (*(volatile uint32_t*)0x2600007c) +#define reg_mprj_io_24 (*(volatile uint32_t*)0x26000080) +#define reg_mprj_io_25 (*(volatile uint32_t*)0x26000084) +#define reg_mprj_io_26 (*(volatile uint32_t*)0x26000088) + +#define reg_mprj_io_27 (*(volatile uint32_t*)0x2600008c) +#define reg_mprj_io_28 (*(volatile uint32_t*)0x26000090) +#define reg_mprj_io_29 (*(volatile uint32_t*)0x26000094) +#define reg_mprj_io_30 (*(volatile uint32_t*)0x26000098) +#define reg_mprj_io_31 (*(volatile uint32_t*)0x2600009c) + +#define reg_mprj_io_32 (*(volatile uint32_t*)0x260000a0) +#define reg_mprj_io_33 (*(volatile uint32_t*)0x260000a4) +#define reg_mprj_io_34 (*(volatile uint32_t*)0x260000a8) +#define reg_mprj_io_35 (*(volatile uint32_t*)0x260000ac) +#define reg_mprj_io_36 (*(volatile uint32_t*)0x260000b0) +#define reg_mprj_io_37 (*(volatile uint32_t*)0x260000b4) + +// User Project Slaves (0x3000_0000) +#define reg_mprj_slave (*(volatile uint32_t*)0x30000000) + +// Flash Control SPI Configuration (2D00_0000) +#define reg_spictrl (*(volatile uint32_t*)0x2d000000) + +// Bit fields for Flash SPI control +#define FLASH_BITBANG_IO0 0x00000001 +#define FLASH_BITBANG_IO1 0x00000002 +#define FLASH_BITBANG_CLK 0x00000010 +#define FLASH_BITBANG_CSB 0x00000020 +#define FLASH_BITBANG_OEB0 0x00000100 +#define FLASH_BITBANG_OEB1 0x00000200 +#define FLASH_ENABLE 0x80000000 + +// Counter-Timer 0 Configuration +#define reg_timer0_config (*(volatile uint32_t*)0x22000000) +#define reg_timer0_value (*(volatile uint32_t*)0x22000004) +#define reg_timer0_data (*(volatile uint32_t*)0x22000008) + +// Counter-Timer 1 Configuration +#define reg_timer1_config (*(volatile uint32_t*)0x23000000) +#define reg_timer1_value (*(volatile uint32_t*)0x23000004) +#define reg_timer1_data (*(volatile uint32_t*)0x23000008) + +// Bit fields for Counter-timer configuration +#define TIMER_ENABLE 0x01 +#define TIMER_ONESHOT 0x02 +#define TIMER_UPCOUNT 0x04 +#define TIMER_CHAIN 0x08 +#define TIMER_IRQ_ENABLE 0x10 + +// SPI Master Configuration +#define reg_spimaster_config (*(volatile uint32_t*)0x24000000) +#define reg_spimaster_data (*(volatile uint32_t*)0x24000004) + +// Bit fields for SPI master configuration +#define SPI_MASTER_DIV_MASK 0x00ff +#define SPI_MASTER_MLB 0x0100 +#define SPI_MASTER_INV_CSB 0x0200 +#define SPI_MASTER_INV_CLK 0x0400 +#define SPI_MASTER_MODE_1 0x0800 +#define SPI_MASTER_STREAM 0x1000 +#define SPI_MASTER_ENABLE 0x2000 +#define SPI_MASTER_IRQ_ENABLE 0x4000 +#define SPI_HOUSEKEEPING_CONN 0x8000 + +// System Area (0x2F00_0000) +#define reg_power_good (*(volatile uint32_t*)0x2F000000) +#define reg_clk_out_dest (*(volatile uint32_t*)0x2F000004) +#define reg_trap_out_dest (*(volatile uint32_t*)0x2F000008) +#define reg_irq_source (*(volatile uint32_t*)0x2F00000C) + +// Bit fields for reg_power_good +#define USER1_VCCD_POWER_GOOD 0x01 +#define USER2_VCCD_POWER_GOOD 0x02 +#define USER1_VDDA_POWER_GOOD 0x04 +#define USER2_VDDA_POWER_GOOD 0x08 + +// Bit fields for reg_clk_out_dest +#define CLOCK1_MONITOR 0x01 +#define CLOCK2_MONITOR 0x02 + +// Bit fields for reg_irq_source +#define IRQ7_SOURCE 0x01 +#define IRQ8_SOURCE 0x02 + +// Individual bit fields for the GPIO pad control +#define MGMT_ENABLE 0x0001 +#define OUTPUT_DISABLE 0x0002 +#define HOLD_OVERRIDE 0x0004 +#define INPUT_DISABLE 0x0008 +#define MODE_SELECT 0x0010 +#define ANALOG_ENABLE 0x0020 +#define ANALOG_SELECT 0x0040 +#define ANALOG_POLARITY 0x0080 +#define SLOW_SLEW_MODE 0x0100 +#define TRIPPOINT_SEL 0x0200 +#define DIGITAL_MODE_MASK 0x1c00 + +// Useful GPIO mode values +#define GPIO_MODE_MGMT_STD_INPUT_NOPULL 0x0403 +#define GPIO_MODE_MGMT_STD_INPUT_PULLDOWN 0x0803 +#define GPIO_MODE_MGMT_STD_INPUT_PULLUP 0x0c03 +#define GPIO_MODE_MGMT_STD_OUTPUT 0x1809 + +#define GPIO_MODE_USER_STD_INPUT_NOPULL 0x0402 +#define GPIO_MODE_USER_STD_INPUT_PULLDOWN 0x0802 +#define GPIO_MODE_USER_STD_INPUT_PULLUP 0x0c02 +#define GPIO_MODE_USER_STD_OUTPUT 0x1808 + +// -------------------------------------------------------- +#endif
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/Makefile new file mode 100644 index 0000000..c7fd2d9 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/Makefile
@@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# ---- Test patterns for project striVe ---- + +.SUFFIXES: +.SILENT: clean all + +PATTERNS = gpio mem uart perf hkspi sysctrl mprj_ctrl pass_thru timer timer2 pll storage + +all: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && SIM=RTL make -f Makefile $${i}.vcd &> verify.log && grep Monitor verify.log) ; \ + ( cd $$i && SIM=GL make -f Makefile $${i}.vcd &> verify.log && grep Monitor verify.log) ; \ + done + +clean: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make clean ) ; \ + done + +.PHONY: clean all
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/gpio/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/gpio/Makefile new file mode 100644 index 0000000..5724f98 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/gpio/Makefile
@@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = gpio + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/gpio/README b/verilog/dv/caravel/caravel/mgmt_soc/gpio/README new file mode 100644 index 0000000..baadc1f --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/gpio/README
@@ -0,0 +1,44 @@ +<!--- +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +--> +------------------------------------------------ +Caravel +gpio testbench +------------------------------------------------ + +This testbench exercises the fundamental use of the Caravel +management SoC to drive the I/O in the user area as general +purpose I/O on startup. + +On startup, all GPIO are configured as input to the management +region (so as to be high impedence to the external world) and +decoupled from the user project area. + +To configure any GPIO as output, the appropriate memory-mapped +location for the I/O must be properly configured. Since the +I/O configuration is stored in two places, in the SoC, but +also locally at each I/O pad, the "transfer" bit must be +applied, which initiates a transfer of the configuration data +around the padframe. + +The testbench takes 16 pins from the user area and checks +functionality by applying input values on 8 of these pins from +the testbench verilog, detecting them in the C program, then +copying the values to the other 8 pins, and detecting those +values in the testbench verilog. + +If any of that does not work, then the testbench will fail.
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/gpio/gpio.c b/verilog/dv/caravel/caravel/mgmt_soc/gpio/gpio.c new file mode 100644 index 0000000..73dd397 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/gpio/gpio.c
@@ -0,0 +1,115 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + * GPIO Test + * Tests PU and PD on the lower 8 pins while being driven from outside + * Tests Writing to the upper 8 pins + * Tests reading from the lower 8 pins + */ + +void main() +{ + int i; + + /* Set data out to zero */ + reg_mprj_datal = 0; + + /* Lower 8 pins are input and upper 8 pins are output */ + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_NOPULL; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // change the pull up and pull down (checked by the TB) + reg_mprj_datal = 0xa0000000; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + reg_mprj_datal = 0x0b000000; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN; + + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_PULLUP; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // read the lower 8 pins, add 1 then output the result + // checked by the TB + reg_mprj_datal = 0xab000000; + + while (1){ + int x = (reg_mprj_datal & 0xff0000) >> 16; + reg_mprj_datal = (x+1) << 24; + } +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/gpio/gpio_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/gpio/gpio_tb.v new file mode 100644 index 0000000..f46fee9 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/gpio/gpio_tb.v
@@ -0,0 +1,192 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module gpio_tb; + + reg clock; + reg power1; + reg power2; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock <= 0; + end + + initial begin + $dumpfile("gpio.vcd"); + $dumpvars(0, gpio_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (25) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test GPIO (GL) Failed"); + `else + $display ("Monitor: Timeout, Test GPIO (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + wire [37:0] mprj_io; // Most of these are no-connects + wire [15:0] checkbits; + reg [7:0] checkbits_lo; + wire [7:0] checkbits_hi; + + assign mprj_io[23:16] = checkbits_lo; + assign checkbits = mprj_io[31:16]; + assign checkbits_hi = checkbits[15:8]; + assign mprj_io[3] = 1'b1; // Force CSB high. + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire gpio; + + reg RSTB; + + // Transactor + initial begin + checkbits_lo <= {8{1'bz}}; + wait(checkbits_hi == 8'hA0); + checkbits_lo <= 8'hF0; + wait(checkbits_hi == 8'h0B); + checkbits_lo <= 8'h0F; + wait(checkbits_hi == 8'hAB); + checkbits_lo <= 8'h0; + repeat (1000) @(posedge clock); + checkbits_lo <= 8'h1; + repeat (1000) @(posedge clock); + checkbits_lo <= 8'h3; + end + + // Monitor + initial begin + wait(checkbits_hi == 8'hA0); + wait(checkbits[7:0] == 8'hF0); + wait(checkbits_hi == 8'h0B); + wait(checkbits[7:0] == 8'h0F); + wait(checkbits_hi == 8'hAB); + wait(checkbits[7:0] == 8'h00); + wait(checkbits_hi == 8'h01); + wait(checkbits[7:0] == 8'h01); + wait(checkbits_hi == 8'h02); + wait(checkbits[7:0] == 8'h03); + wait(checkbits_hi == 8'h04); + `ifdef GL + $display("Monitor: Test GPIO (GL) Passed"); + `else + $display("Monitor: Test GPIO (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + + always @(checkbits) begin + #1 $display("GPIO state = %b (%d - %d)", checkbits, + checkbits_hi, checkbits_lo); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + // These are the mappings of mprj_io GPIO pads that are set to + // specific functions on startup: + // + // JTAG = mgmt_gpio_io[0] (inout) + // SDO = mgmt_gpio_io[1] (output) + // SDI = mgmt_gpio_io[2] (input) + // CSB = mgmt_gpio_io[3] (input) + // SCK = mgmt_gpio_io[4] (input) + // ser_rx = mgmt_gpio_io[5] (input) + // ser_tx = mgmt_gpio_io[6] (output) + // irq = mgmt_gpio_io[7] (input) + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("gpio.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/hkspi/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/hkspi/Makefile new file mode 100644 index 0000000..1695a45 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/hkspi/Makefile
@@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# ---- Test patterns for project striVe ---- +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = hkspi + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/hkspi/hkspi.c b/verilog/dv/caravel/caravel/mgmt_soc/hkspi/hkspi.c new file mode 100644 index 0000000..3bfac32 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/hkspi/hkspi.c
@@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} + +// -------------------------------------------------------- + +void main() +{ + // This program is just to keep the processor busy while the + // housekeeping SPI is being accessed, to show that the + // processor is interrupted only when the reset is applied + // through the SPI. + + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xa0000000; + + // Set clock to 64 kbaud and enable the UART + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Test message + print("\n"); + print(" ____ _ ____ ____\n"); + print(" | _ \\(_) ___ ___/ ___| ___ / ___|\n"); + print(" | |_) | |/ __/ _ \\___ \\ / _ \\| |\n"); + print(" | __/| | (_| (_) |__) | (_) | |___\n"); + print(" |_| |_|\\___\\___/____/ \\___/ \\____|\n"); + + reg_mprj_datal = 0xab000000; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/hkspi/hkspi_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/hkspi/hkspi_tb.v new file mode 100644 index 0000000..50ea981 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/hkspi/hkspi_tb.v
@@ -0,0 +1,430 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none +/* + StriVe housekeeping SPI testbench. +*/ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" +`include "tbuart.v" + +module hkspi_tb; + reg clock; + reg SDI, CSB, SCK, RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [37:0] mprj_io; + wire uart_tx; + wire uart_rx; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + + wire SDO; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + // The main testbench is here. Put the housekeeping SPI into + // pass-thru mode and read several bytes from the flash SPI. + + // First define tasks for SPI functions + + task start_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b0; + #50; + end + endtask + + task end_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b1; + #50; + end + endtask + + task write_byte; + input [7:0] odata; + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_byte; + output [7:0] idata; + begin + SCK <= 1'b0; + SDI <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_write_byte + (input [7:0] odata, + output [7:0] idata); + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + integer i; + + // Now drive the digital signals on the housekeeping SPI + reg [7:0] tbdata; + + initial begin + $dumpfile("hkspi.vcd"); + $dumpvars(0, hkspi_tb); + + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + // Delay, then bring chip out of reset + #1000; + RSTB <= 1'b1; + #2000; + + // First do a normal read from the housekeeping SPI to + // make sure the housekeeping SPI works. + + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) + read_byte(tbdata); + end_csb(); + #10; + $display("Read data = 0x%02x (should be 0x10)", tbdata); + + // Toggle external reset + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h07); // Address (register 7 = external reset) + write_byte(8'h01); // Data = 0x01 (apply external reset) + end_csb(); + + start_csb(); + write_byte(8'h80); // Write stream command + write_byte(8'h07); // Address (register 7 = external reset) + write_byte(8'h00); // Data = 0x00 (release external reset) + end_csb(); + + // Read all registers (0 to 18) + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h00); // Address (register 3 = product ID) + read_byte(tbdata); + + $display("Read register 0 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 1 = 0x%02x (should be 0x04)", tbdata); + if(tbdata !== 8'h04) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 2 = 0x%02x (should be 0x56)", tbdata); + if(tbdata !== 8'h56) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed, %02x", tbdata); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed, %02x", tbdata); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 3 = 0x%02x (should be 0x10)", tbdata); + if(tbdata !== 8'h10) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed, %02x", tbdata); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed, %02x", tbdata); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 4 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 5 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 6 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 7 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 8 = 0x%02x (should be 0x02)", tbdata); + if(tbdata !== 8'h02) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 9 = 0x%02x (should be 0x01)", tbdata); + if(tbdata !== 8'h01) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 10 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 11 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 12 = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 13 = 0x%02x (should be 0xff)", tbdata); + if(tbdata !== 8'hff) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 14 = 0x%02x (should be 0xef)", tbdata); + if(tbdata !== 8'hef) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 15 = 0x%02x (should be 0xff)", tbdata); + if(tbdata !== 8'hff) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 16 = 0x%02x (should be 0x03)", tbdata); + if(tbdata !== 8'h03) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 17 = 0x%02x (should be 0x12)", tbdata); + if(tbdata !== 8'h12) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read register 18 = 0x%02x (should be 0x04)", tbdata); + if(tbdata !== 8'h04) begin + `ifdef GL + $display("Monitor: Test HK SPI (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI (RTL) Failed"); $finish; + `endif + end + + end_csb(); + + `ifdef GL + $display("Monitor: Test HK SPI (GL) Passed"); + `else + $display("Monitor: Test HK SPI (RTL) Passed"); + `endif + + #10000; + $finish; + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + wire hk_sck; + wire hk_csb; + wire hk_sdi; + + assign hk_sck = SCK; + assign hk_csb = CSB; + assign hk_sdi = SDI; + + assign checkbits = mprj_io[31:16]; + assign uart_tx = mprj_io[6]; + assign mprj_io[5] = uart_rx; + assign mprj_io[4] = hk_sck; + assign mprj_io[3] = hk_csb; + assign mprj_io[2] = hk_sdi; + assign SDO = mprj_io[1]; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("hkspi.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + + tbuart tbuart ( + .ser_rx(uart_tx) + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/mem/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/mem/Makefile new file mode 100644 index 0000000..2be8c42 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/mem/Makefile
@@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = mem + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/mem/mem.c b/verilog/dv/caravel/caravel/mgmt_soc/mem/mem.c new file mode 100644 index 0000000..a3b6fcc --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/mem/mem.c
@@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + Memory Test + It uses GPIO to flag the success or failure of the test +*/ +unsigned int ints[10]; +unsigned short shorts[10]; +unsigned char bytes[10]; + +void main() +{ + int i; + + /* Upper 16 user area pins are configured to be GPIO output */ + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // start test + reg_mprj_datal = 0xA0400000; + + // Test Word R/W + for (i=0; i<10; i++) + ints[i] = i*5000 + 10000; + + for (i=0; i<10; i++) + if ((i*5000+10000) != ints[i]) + reg_mprj_datal = 0xAB400000; + + reg_mprj_datal = 0xAB410000; + + // Test Half Word R/W + reg_mprj_datal = 0xA0200000; + for (i=0; i<10; i++) + shorts[i] = i*500 + 100; + + for(i=0; i<10; i++) + if((i*500+100) != shorts[i]) + reg_mprj_datal = 0xAB200000; + + reg_mprj_datal = 0xAB210000; + + // Test byte R/W + reg_mprj_datal = 0xA0100000; + for(i=0; i<10; i++) + bytes[i] = i*5 + 10; + + for(i=0; i<10; i++) + if((i*5+10) != bytes[i]) + reg_mprj_datal = 0xAB100000; + + reg_mprj_datal = 0xAB110000; +} \ No newline at end of file
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/mem/mem_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/mem/mem_tb.v new file mode 100644 index 0000000..a82184c --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/mem/mem_tb.v
@@ -0,0 +1,199 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module mem_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [37:0] mprj_io; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + assign checkbits = mprj_io[31:16]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("mem.vcd"); + $dumpvars(0, mem_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (100) begin + repeat (1000) @(posedge clock); + //$display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test MEM (GL) Failed"); + `else + $display ("Monitor: Timeout, Test MEM (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + if(checkbits == 16'hA040) begin + $display("Mem Test (word rw) started"); + end + else if(checkbits == 16'hAB40) begin + $display("%c[1;31m",27); + `ifdef GL + $display("Monitor: Test MEM (GL) [word rw] failed"); + `else + $display("Monitor: Test MEM (RTL) [word rw] failed"); + `endif + $display("%c[0m",27); + $finish; + end + else if(checkbits == 16'hAB41) begin + `ifdef GL + $display("Monitor: Test MEM (GL) [word rw] passed"); + `else + $display("Monitor: Test MEM (RTL) [word rw] passed"); + `endif + end + else if(checkbits == 16'hA020) begin + $display("Mem Test (short rw) started"); + end + else if(checkbits == 16'hAB20) begin + $display("%c[1;31m",27); + `ifdef GL + $display("Monitor: Test MEM (GL) [short rw] failed"); + `else + $display("Monitor: Test MEM (RTL) [short rw] failed"); + `endif + $display("%c[0m",27); + $finish; + end + else if(checkbits == 16'hAB21) begin + `ifdef GL + $display("Monitor: Test MEM (GL) [short rw] passed"); + `else + $display("Monitor: Test MEM (RTL) [short rw] passed"); + `endif + end + else if(checkbits == 16'hA010) begin + $display("Mem Test (byte rw) started"); + end + else if(checkbits == 16'hAB10) begin + $display("%c[1;31m",27); + `ifdef GL + $display("Monitor: Test MEM (GL) [byte rw] failed"); + `else + $display("Monitor: Test MEM (RTL) [byte rw] failed"); + `endif + $display("%c[0m",27); + $finish; + end + else if(checkbits == 16'hAB11) begin + `ifdef GL + $display("Monitor: Test MEM (GL) [byte rw] passed"); + `else + $display("Monitor: Test MEM (RTL) [byte rw] passed"); + `endif + $finish; + end + + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD3V3 = power1; + assign VDD1V8 = power2; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("mem.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/Makefile new file mode 100644 index 0000000..64e99ed --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/Makefile
@@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = mprj_ctrl + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/mprj_ctrl.c b/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/mprj_ctrl.c new file mode 100644 index 0000000..1d7a140 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/mprj_ctrl.c
@@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + * User Project IO Control Test + */ + +void main() +{ + /* All GPIO pins are configured to be output */ + /* The lower 28 bits are connected to the user */ + /* project to output the counter result, and the */ + /* upper 4 bits are connected to the management */ + /* SoC to apply values that can be flagged by the */ + /* testbench for specific benchmark tests. */ + + /* GPIOs 31 to 16 are connected to the management SoC */ + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* GPIOs 27 to 0 are connected to the user area */ + reg_mprj_io_27 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_15 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_6 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_USER_STD_OUTPUT; + // reg_mprj_io_3 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_USER_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + reg_mprj_datal = 0; + + // start test + reg_mprj_datal = 0x50000000; + + // Write to IO Control + reg_mprj_io_0 = 0x004F; + if (reg_mprj_io_0 != 0x004F) + reg_mprj_datal = 0x60000000; + else + reg_mprj_datal = 0x70000000; + + // Write to IO Control + reg_mprj_io_1 = 0x005F; + if (reg_mprj_io_1 != 0x005F) + reg_mprj_datal = 0x80000000; + else + reg_mprj_datal = 0x90000000; + + // Write to IO Control + reg_mprj_io_2 = 0x006F; + if (reg_mprj_io_2 != 0x006F) + reg_mprj_datal = 0xA0000000; + else + reg_mprj_datal = 0xb0000000; + + // Write to IO Control (NOTE: Only 13 bits are valid) + reg_mprj_io_3 = 0xF0F5; + if (reg_mprj_io_3 != 0x10F5) + reg_mprj_datal = 0xc0000000; + else + reg_mprj_datal = 0xd0000000; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/mprj_ctrl_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/mprj_ctrl_tb.v new file mode 100644 index 0000000..ae04001 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/mprj_ctrl/mprj_ctrl_tb.v
@@ -0,0 +1,175 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module mprj_ctrl_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire [37:0] user_io; + wire SDO; + + wire [3:0] checkbits; + + assign checkbits = user_io[31:28]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("mprj_ctrl.vcd"); + $dumpvars(0, mprj_ctrl_tb); + repeat (25) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test User Project (GL) Failed"); + `else + $display ("Monitor: Timeout, Test User Project (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + always @(checkbits) begin + if(checkbits == 4'h5) begin + $display("User Project control Test started"); + end else if(checkbits == 4'h6) begin + $display("%c[1;31m",27); + $display("Monitor: IO control R/W failed (check 6)"); + $display("%c[0m",27); + $finish; + end else if(checkbits == 4'h7) begin + $display("Monitor: IO control R/W passed (check 7)"); + end else if(checkbits == 4'h8) begin + $display("%c[1;31m",27); + $display("Monitor: power control R/W failed (check 8)"); + $display("%c[0m",27); + $finish; + end else if(checkbits == 4'h9) begin + $display("Monitor: power control R/W passed (check 9)"); + end else if(checkbits == 4'ha) begin + $display("%c[1;31m",27); + $display("Monitor: power control R/W failed (check 10)"); + $display("%c[0m",27); + $finish; + end else if(checkbits == 4'hb) begin + $display("Monitor: power control R/W passed (check 11)"); + end else if(checkbits == 4'hc) begin + $display("%c[1;31m",27); + $display("Monitor: power control R/W failed (check 12)"); + $display("%c[0m",27); + $finish; + end else if(checkbits == 4'hd) begin + + $display("Monitor: power control R/W passed (check 13)"); + `ifdef GL + $display("Monitor: User Project control (GL) test passed."); + `else + $display("Monitor: User Project control (RTL) test passed."); + `endif + $finish; + end + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(gpio) begin + #1 $display("GPIO state = %b ", gpio); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign user_io[3] = 1'b1; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (user_io), + .flash_csb (flash_csb), + .flash_clk (flash_clk), + .flash_io0 (flash_io0), + .flash_io1 (flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("mprj_ctrl.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/Makefile new file mode 100644 index 0000000..2fba759 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/Makefile
@@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# ---- Test patterns for project striVe ---- +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = pass_thru + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/pass_thru.c b/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/pass_thru.c new file mode 100644 index 0000000..33a981d --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/pass_thru.c
@@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} + +// -------------------------------------------------------- + +void main() +{ + // This program is just to keep the processor busy while the + // housekeeping SPI is being accessed. to show that the + // processor is halted while the SPI is accessing the + // flash SPI in pass-through mode. + + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xa0000000; + + // Set clock to 64 kbaud and enable the UART + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Test in progress + reg_mprj_datal = 0xa5000000; + + // Test message + print("Test message\n"); + + // End test + reg_mprj_datal = 0xab000000; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/pass_thru_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/pass_thru_tb.v new file mode 100644 index 0000000..bb141e1 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/pass_thru/pass_thru_tb.v
@@ -0,0 +1,349 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none +/* + * StriVe housekeeping pass-thru mode SPI testbench. + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" +`include "tbuart.v" + +module pass_thru_tb; + reg clock; + reg SDI, CSB, SCK, RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [37:0] mprj_io; + wire uart_tx; + wire uart_rx; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire flash_io2; + wire flash_io3; + + wire SDO; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + // The main testbench is here. Put the housekeeping SPI into + // pass-thru mode and read several bytes from the flash SPI. + + // First define tasks for SPI functions + + task start_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b0; + #50; + end + endtask + + task end_csb; + begin + SCK <= 1'b0; + SDI <= 1'b0; + CSB <= 1'b1; + #50; + end + endtask + + task write_byte; + input [7:0] odata; + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_byte; + output [7:0] idata; + begin + SCK <= 1'b0; + SDI <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + task read_write_byte + (input [7:0] odata, + output [7:0] idata); + begin + SCK <= 1'b0; + for (i=7; i >= 0; i--) begin + #50; + SDI <= odata[i]; + idata[i] = SDO; + #50; + SCK <= 1'b1; + #100; + SCK <= 1'b0; + end + end + endtask + + integer i; + + // Now drive the digital signals on the housekeeping SPI + reg [7:0] tbdata; + + initial begin + $dumpfile("pass_thru.vcd"); + $dumpvars(0, pass_thru_tb); + + CSB <= 1'b1; + SCK <= 1'b0; + SDI <= 1'b0; + RSTB <= 1'b0; + + #2000; + + RSTB <= 1'b1; + + // Wait on start of program execution + wait(checkbits == 16'hA000); + + // First do a normal read from the housekeeping SPI to + // make sure the housekeeping SPI works. + + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) + read_byte(tbdata); + end_csb(); + #10; + $display("Read data = 0x%02x (should be 0x10)", tbdata); + if(tbdata !== 8'h10) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + + start_csb(); + write_byte(8'hc4); // Pass-thru mode + write_byte(8'h03); // Command 03 (read values w/3-byte address + write_byte(8'h00); // Address is next three bytes (0x000000) + write_byte(8'h00); + write_byte(8'h00); + + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x93)", tbdata); + if(tbdata !== 8'h93) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x93)", tbdata); + if(tbdata !== 8'h93) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x01)", tbdata); + if(tbdata !== 8'h01) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + read_byte(tbdata); + $display("Read flash data = 0x%02x (should be 0x00)", tbdata); + if(tbdata !== 8'h00) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + + end_csb(); + + // Wait for processor to restart + wait(checkbits == 16'hA000); + + // Read product ID register again + + start_csb(); + write_byte(8'h40); // Read stream command + write_byte(8'h03); // Address (register 3 = product ID) + read_byte(tbdata); + end_csb(); + #10; + $display("Read data = 0x%02x (should be 0x10)", tbdata); + if(tbdata !== 8'h10) begin + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Failed"); $finish; + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Failed"); $finish; + `endif + end + + `ifdef GL + $display("Monitor: Test HK SPI Pass-thru (GL) Passed"); + `else + $display("Monitor: Test HK SPI Pass-thru (RTL) Passed"); + `endif + + #10000; + $finish; + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + wire hk_sck; + wire hk_csb; + wire hk_sdi; + + assign hk_sck = SCK; + assign hk_csb = CSB; + assign hk_sdi = SDI; + + assign checkbits = mprj_io[31:16]; + assign uart_tx = mprj_io[6]; + assign mprj_io[5] = uart_rx; + assign mprj_io[4] = hk_sck; + assign mprj_io[3] = hk_csb; + assign mprj_io[2] = hk_sdi; + assign SDO = mprj_io[1]; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("pass_thru.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + + tbuart tbuart ( + .ser_rx(uart_tx) + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/perf/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/perf/Makefile new file mode 100644 index 0000000..ed26dce --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/perf/Makefile
@@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +RTL_PATH = ../../../../rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = perf + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/perf/perf.c b/verilog/dv/caravel/caravel/mgmt_soc/perf/perf.c new file mode 100644 index 0000000..5a17ba2 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/perf/perf.c
@@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + Performance Test + It uses GPIO to flag the success or failure of the test +*/ +unsigned int ints[50]; +unsigned short shorts[50]; +unsigned char bytes[50]; + +int main() +{ + int i; + int sum = 0; + + /* Upper 16 user area pins are configured to be GPIO output */ + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + reg_mprj_datal = 0; + + // start test + reg_mprj_datal = 0xA0000000; + + for (i=0; i<100; i++) + sum += (sum + i); + + reg_mprj_datal = 0xAB000000; + + return sum; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/perf/perf_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/perf/perf_tb.v new file mode 100644 index 0000000..c086226 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/perf/perf_tb.v
@@ -0,0 +1,155 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module perf_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [37:0] mprj_io; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + assign checkbits = mprj_io[31:16]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + reg [31:0] kcycles; + + initial begin + $dumpfile("perf.vcd"); + $dumpvars(0, perf_tb); + + kcycles = 0; + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (150) begin + repeat (1000) @(posedge clock); + //$display("+1000 cycles"); + kcycles <= kcycles + 1; + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test Performance (GL) Failed"); + `else + $display ("Monitor: Timeout, Test Performance (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + //#1 $display("GPIO state = %X ", gpio); + if(checkbits == 16'hA000) begin + kcycles = 0; + $display("Performance Test started"); + end + else if(checkbits == 16'hAB00) begin + //$display("Monitor: number of cycles/100 iterations: %d KCycles", kcycles); + `ifdef GL + $display("Monitor: Test Performance (GL) passed [%0d KCycles]", kcycles); + `else + $display("Monitor: Test Performance (RTL) passed [%0d KCycles]", kcycles); + `endif + $finish; + end + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("perf.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/pll/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/pll/Makefile new file mode 100644 index 0000000..f1f19aa --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/pll/Makefile
@@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = pll + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/pll/pll.c b/verilog/dv/caravel/caravel/mgmt_soc/pll/pll.c new file mode 100644 index 0000000..81a1fc6 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/pll/pll.c
@@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + * PLL Test (self-switching) + * - Enables SPI master + * - Uses SPI master to internally access the housekeeping SPI + * - Switches PLL bypass + * - Changes PLL divider + * + * Tesbench mostly copied from sysctrl + */ +void main() +{ + int i; + + reg_mprj_datal = 0; + + // Configure upper 16 bits of user GPIO for generating testbench + // checkpoints. + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xA0400000; + + // Enable SPI master + // SPI master configuration bits: + // bits 7-0: Clock prescaler value (default 2) + // bit 8: MSB/LSB first (0 = MSB first, 1 = LSB first) + // bit 9: CSB sense (0 = inverted, 1 = noninverted) + // bit 10: SCK sense (0 = noninverted, 1 = inverted) + // bit 11: mode (0 = read/write opposite edges, 1 = same edges) + // bit 12: stream (1 = CSB ends transmission) + // bit 13: enable (1 = enabled) + // bit 14: IRQ enable (1 = enabled) + // bit 15: Connect to housekeeping SPI (1 = connected) + + reg_spimaster_config = 0xa002; // Enable, prescaler = 2, + // connect to housekeeping SPI + + // Apply stream read (0x40 + 0x03) and read back one byte + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x80; // Write 0x80 (write mode) + reg_spimaster_data = 0x08; // Write 0x18 (start address) + reg_spimaster_data = 0x01; // Write 0x01 to PLL enable, no DCO mode + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x80; // Write 0x80 (write mode) + reg_spimaster_data = 0x11; // Write 0x11 (start address) + reg_spimaster_data = 0x03; // Write 0x03 to PLL output divider + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x80; // Write 0x80 (write mode) + reg_spimaster_data = 0x09; // Write 0x09 (start address) + reg_spimaster_data = 0x00; // Write 0x00 to clock from PLL (no bypass) + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + + // Write checkpoint + reg_mprj_datal = 0xA0410000; + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x80; // Write 0x80 (write mode) + reg_spimaster_data = 0x12; // Write 0x12 (start address) + reg_spimaster_data = 0x03; // Write 0x03 to feedback divider (was 0x04) + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + + // Write checkpoint + reg_mprj_datal = 0xA0420000; + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x80; // Write 0x80 (write mode) + reg_spimaster_data = 0x11; // Write 0x11 (start address) + reg_spimaster_data = 0x04; // Write 0x04 to PLL output divider + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + + reg_spimaster_config = 0x2102; // Release housekeeping SPI + + // End test + reg_mprj_datal = 0xA0900000; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/pll/pll_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/pll/pll_tb.v new file mode 100644 index 0000000..fd0f11e --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/pll/pll_tb.v
@@ -0,0 +1,167 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module pll_tb; + reg clock; + reg power1; + reg power2; + reg RSTB; + + wire gpio; + wire [15:0] checkbits; + wire [7:0] spivalue; + wire [37:0] mprj_io; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire SDO; + + assign checkbits = mprj_io[31:16]; + assign spivalue = mprj_io[15:8]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("pll.vcd"); + $dumpvars(0, pll_tb); + repeat (25) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test PLL (GL) Failed"); + `else + $display ("Monitor: Timeout, Test PLL (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + // Monitor + initial begin + wait(checkbits == 16'hA040); + `ifdef GL + $display("Monitor: Test PLL (GL) Started"); + `else + $display("Monitor: Test PLL (RTL) Started"); + `endif + + wait(checkbits == 16'hA041); + // $display(" SPI value = 0x%x (should be 0x04)", spivalue); + // if(spivalue !== 32'h04) begin + // $display("Monitor: Test PLL (RTL) Failed"); + // $finish; + // end + wait(checkbits == 16'hA042); + // $display(" SPI value = 0x%x (should be 0x56)", spivalue); + // if(spivalue !== 32'h56) begin + // $display("Monitor: Test PLL (RTL) Failed"); + // $finish; + // end + + wait(checkbits == 16'hA090); + `ifdef GL + $display("Monitor: Test PLL (GL) Passed"); + `else + $display("Monitor: Test PLL (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + #1 $display("GPIO state = %b ", checkbits); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("pll.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/storage/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/storage/Makefile new file mode 100644 index 0000000..11b0b04 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/storage/Makefile
@@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = storage + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/storage/storage.c b/verilog/dv/caravel/caravel/mgmt_soc/storage/storage.c new file mode 100644 index 0000000..55fdd98 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/storage/storage.c
@@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + Storage area Test + It uses GPIO to flag the success or failure of the test +*/ + +void main() +{ + int i; + volatile uint32_t* ram_addr; + /* Upper 16 user area pins are configured to be GPIO output */ + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Apply configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // start test + reg_mprj_datal = 0xA0400000; + + // Test Management R/W block0 + for (i=0; i<10; i++){ + ram_addr = ®_rw_block0 + i; + *ram_addr = i*5000 + 10000; + } + + for (i=0; i<10; i++){ + ram_addr = ®_rw_block0 + i; + if ((i*5000+10000) != *ram_addr) + reg_mprj_datal = 0xAB400000; + } + + reg_mprj_datal = 0xAB410000; + + // Test Management R/W block1 + reg_mprj_datal = 0xA0200000; + for (i=0; i<10; i++){ + ram_addr = ®_rw_block1 + i; + *ram_addr = i*5000 + 10000; + } + + for (i=0; i<10; i++){ + ram_addr = ®_rw_block1 + i; + if ((i*5000+10000) != *ram_addr) + reg_mprj_datal = 0xAB200000; + } + + reg_mprj_datal = 0xAB210000; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/storage/storage_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/storage/storage_tb.v new file mode 100644 index 0000000..cfbe150 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/storage/storage_tb.v
@@ -0,0 +1,186 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module storage_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [37:0] mprj_io; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + assign checkbits = mprj_io[31:16]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("storage.vcd"); + $dumpvars(0, storage_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (100) begin + repeat (1000) @(posedge clock); + //$display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test Storage (GL) Failed"); + `else + $display ("Monitor: Timeout, Test Storage (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + if(checkbits == 16'hA040) begin + `ifdef GL + $display("Mem Test storage MGMT block0 (GL) [word rw] started"); + `else + $display("Mem Test storage MGMT block0 (RTL) [word rw] started"); + `endif + end + else if(checkbits == 16'hAB40) begin + $display("%c[1;31m",27); + `ifdef GL + $display("Monitor: Test storage MGMT block0 (GL) [word rw] failed"); + `else + $display("Monitor: Test storage MGMT block0 (RTL) [word rw] failed"); + `endif + $display("%c[0m",27); + $finish; + end + else if(checkbits == 16'hAB41) begin + `ifdef GL + $display("Monitor: Test storage MGMT block0 (GL) [word rw] passed"); + `else + $display("Monitor: Test storage MGMT block0 (RTL) [word rw] passed"); + `endif + end + else if(checkbits == 16'hA020) begin + `ifdef GL + $display("Mem Test storage MGMT block1 (GL) [word rw] started"); + `else + $display("Mem Test storage MGMT block1 (RTL) [word rw] started"); + `endif + end + else if(checkbits == 16'hAB20) begin + $display("%c[1;31m",27); + `ifdef GL + $display("Monitor: Test storage MGMT block1 (GL) [word rw] failed"); + `else + $display("Monitor: Test storage MGMT block1 (RTL) [word rw] failed"); + `endif + $display("%c[0m",27); + $finish; + end + else if(checkbits == 16'hAB21) begin + `ifdef GL + $display("Monitor: Test storage MGMT block1 (GL) [word rw] passed"); + `else + $display("Monitor: Test storage MGMT block1 (RTL) [word rw] passed"); + `endif + $finish; + end + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VSS = 1'b0; + assign VDD3V3 = power1; + assign VDD1V8 = power2; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("storage.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/Makefile new file mode 100644 index 0000000..4816f03 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/Makefile
@@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = sysctrl + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/sysctrl.c b/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/sysctrl.c new file mode 100644 index 0000000..0f5d56d --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/sysctrl.c
@@ -0,0 +1,165 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + * System Control Test + * - Enables SPI master + * - Uses SPI master to internally access the housekeeping SPI + * - Reads default value of SPI-Controlled registers + * - Flags failure/success using mprj_io + */ +void main() +{ + int i; + uint32_t value; + + reg_mprj_datal = 0; + + // Configure upper 16 bits of user GPIO for generating testbench + // checkpoints. + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Configure next 8 bits for writing the SPI value read on GPIO + reg_mprj_io_15 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xA0400000; + + // Enable SPI master + // SPI master configuration bits: + // bits 7-0: Clock prescaler value (default 2) + // bit 8: MSB/LSB first (0 = MSB first, 1 = LSB first) + // bit 9: CSB sense (0 = inverted, 1 = noninverted) + // bit 10: SCK sense (0 = noninverted, 1 = inverted) + // bit 11: mode (0 = read/write opposite edges, 1 = same edges) + // bit 12: stream (1 = CSB ends transmission) + // bit 13: enable (1 = enabled) + // bit 14: IRQ enable (1 = enabled) + // bit 15: Connect to housekeeping SPI (1 = connected) + + reg_spimaster_config = 0xa002; // Enable, prescaler = 2, + // connect to housekeeping SPI + + // Apply stream read (0x40 + 0x03) and read back one byte + + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x40; // Write 0x40 (read mode) + reg_spimaster_data = 0x01; // Write 0x01 (start address) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0410000 | (value << 8); // Mfgr ID (high) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0420000 | (value << 8); // Mfgr ID (low) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0430000 | (value << 8); // Prod ID + + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x40; // Write 0x40 (read mode) + reg_spimaster_data = 0x08; // Write 0x08 (start address) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0440000 | (value << 8); // PLL enable + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0450000 | (value << 8); // PLL bypass + + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + reg_spimaster_config = 0xb002; // Apply stream mode + reg_spimaster_data = 0x40; // Write 0x40 (read mode) + reg_spimaster_data = 0x0d; // Write 0x0d (start address) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0460000 | (value << 8); // PLL trim (2 high bits) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0470000 | (value << 8); // PLL trim (2nd byte) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0480000 | (value << 8); // PLL trim (3rd byte) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA0490000 | (value << 8); // PLL trim (low byte) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA04a0000 | (value << 8); // PLL select (3 lowest bits) + + reg_spimaster_data = 0x00; // Write 0x00 for read + value = reg_spimaster_data; // Read back byte + // Write checkpoint + reg_mprj_datal = 0xA04b0000 | (value << 8); // PLL divider (5 lowest bits) + + reg_spimaster_config = 0xa102; // Release CSB (ends stream mode) + reg_spimaster_config = 0x2102; // Release housekeeping SPI + + // End test + reg_mprj_datal = 0xA0900000; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/sysctrl_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/sysctrl_tb.v new file mode 100644 index 0000000..b2e6b49 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/sysctrl/sysctrl_tb.v
@@ -0,0 +1,219 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module sysctrl_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire [15:0] checkbits; + wire [7:0] spivalue; + wire [37:0] mprj_io; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire SDO; + + assign checkbits = mprj_io[31:16]; + assign spivalue = mprj_io[15:8]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #10 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("sysctrl.vcd"); + $dumpvars(0, sysctrl_tb); + repeat (25) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test Sysctrl (GL) Failed"); + `else + $display ("Monitor: Timeout, Test Sysctrl (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + // Monitor + initial begin + wait(checkbits == 16'hA040); + `ifdef GL + $display("Monitor: Test Sysctrl (GL) Started"); + `else + $display("Monitor: Test Sysctrl (RTL) Started"); + `endif + wait(checkbits == 16'hA041); + $display(" SPI value = 0x%x (should be 0x04)", spivalue); + if(spivalue !== 32'h04) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA042); + $display(" SPI value = 0x%x (should be 0x56)", spivalue); + if(spivalue !== 32'h56) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA043); + $display(" SPI value = 0x%x (should be 0x10)", spivalue); + if(spivalue !== 32'h10) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA044); + $display(" SPI value = 0x%x (should be 0x02)", spivalue); + if(spivalue !== 32'h02) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA045); + $display(" SPI value = 0x%x (should be 0x01)", spivalue); + if(spivalue !== 32'h01) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA046); + $display(" SPI value = 0x%x (should be 0xff)", spivalue); + if(spivalue !== 32'hff) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA047); + $display(" SPI value = 0x%x (should be 0xef)", spivalue); + if(spivalue !== 32'hef) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA048); + $display(" SPI value = 0x%x (should be 0xff)", spivalue); + if(spivalue !== 32'hff) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA049); + $display(" SPI value = 0x%x (should be 0x03)", spivalue); + if(spivalue !== 32'h03) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA04a); + $display(" SPI value = 0x%x (should be 0x12)", spivalue); + if(spivalue !== 32'h12) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + wait(checkbits == 16'hA04b); + $display(" SPI value = 0x%x (should be 0x04)", spivalue); + if(spivalue !== 32'h04) begin + $display("Monitor: Test Sysctrl Failed"); + $finish; + end + + wait(checkbits == 16'hA090); + `ifdef GL + $display("Monitor: Test Sysctrl (GL) Passed"); + `else + $display("Monitor: Test Sysctrl (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + #1 $display("GPIO state = %b ", checkbits); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("sysctrl.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/timer/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/timer/Makefile new file mode 100644 index 0000000..d7b66b8 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/timer/Makefile
@@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = timer + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/timer/timer.c b/verilog/dv/caravel/caravel/mgmt_soc/timer/timer.c new file mode 100644 index 0000000..e01ed7f --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/timer/timer.c
@@ -0,0 +1,141 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + * Timer Test + */ + +void main() +{ + int i; + uint32_t value; + + /* Initialize output data vector to zero */ + reg_mprj_datah = 0x00000000; + reg_mprj_datal = 0x00000000; + + /* Apply all 38 bits to management standard output. */ + + /* The lower 32 will be used to output the count value */ + /* from the timer. The top 5 bits will be used to mark */ + /* specific checkpoints for the testbench simulation. */ + + reg_mprj_io_37 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_36 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_35 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_34 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_15 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_MGMT_STD_OUTPUT; + // reg_mprj_io_3 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + /* Present start marker (see testbench verilog) */ + reg_mprj_datah = 0x0a; + + /* Configure timer for a single-shot countdown */ + reg_timer0_value = 0xdcba9876; + + /* Timer configuration bits: */ + /* 0 = timer enable (1 = enabled, 0 = disabled) */ + /* 1 = one-shot mode (1 = oneshot, 0 = continuous) */ + /* 2 = up/down (1 = count up, 0 = count down) */ + /* 3 = chain (1 = enabled, 0 = disabled) */ + /* 4 = IRQ enable (1 = enabled, 0 = disabled) */ + + reg_timer0_config = 3; /* Enabled, one-shot, down count */ + + for (i = 0; i < 8; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_timer0_config = 0; /* Disabled */ + + reg_mprj_datah = 0x01; /* Check value in testbench */ + + reg_timer0_value = 0x00000011; + reg_timer0_config = 7; /* Enabled, one-shot, count up */ + + for (i = 0; i < 3; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x02; /* Check value in testbench */ + + reg_timer0_data = 0x00000101; // Set value (will be reset) + reg_timer0_config = 2; /* Disabled, one-shot, count up */ + reg_timer0_config = 5; /* Enabled, continuous, count down */ + + for (i = 0; i < 5; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x03; /* Check value in testbench */ + + reg_timer0_data = 0x00000145; // Force new value + + reg_mprj_datah = 0x04; /* Check value in testbench */ + + for (i = 0; i < 5; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + /* Present end marker (see testbench verilog) */ + reg_mprj_datah = 0x05; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/timer/timer_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/timer/timer_tb.v new file mode 100644 index 0000000..64cf850 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/timer/timer_tb.v
@@ -0,0 +1,197 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module timer_tb; + + reg RSTB; + reg clock; + reg power1, power2; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock <= 0; + end + + initial begin + $dumpfile("timer.vcd"); + $dumpvars(0, timer_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (50) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test GPIO (GL) Failed"); + `else + $display ("Monitor: Timeout, Test GPIO (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + wire [37:0] mprj_io; // Most of these are no-connects + wire [5:0] checkbits; + wire [31:0] countbits; + + assign checkbits = mprj_io[37:32]; + assign countbits = mprj_io[31:0]; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire gpio; + + // Monitor + initial begin + wait(checkbits == 6'h0a); + `ifdef GL + $display("Monitor: Test Timer (GL) Started"); + `else + $display("Monitor: Test Timer (RTL) Started"); + `endif + /* Add checks here */ + wait(checkbits == 6'h01); + $display(" countbits = 0x%x (should be 0xdcba7cfb)", countbits); + if(countbits !== 32'hdcba7cfb) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h02); + $display(" countbits = 0x%x (should be 0x19)", countbits); + if(countbits !== 32'h19) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h03); + $display(" countbits = %x (should be 0x0f)", countbits); + if(countbits !== ((32'h0f) | (3'b100))) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h04); + $display(" countbits = %x (should be 0x0f)", countbits); + if(countbits !== ((32'h0f) | (3'b100))) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + wait(checkbits == 6'h05); + $display(" countbits = %x (should be 0x12bc)", countbits); + if(countbits !== 32'h12bc) begin + $display("Monitor: Test Timer Failed"); + $finish; + end + + `ifdef GL + $display("Monitor: Test Timer (GL) Passed"); + `else + $display("Monitor: Test Timer (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + #1 $display("Timer state = %b (%d)", countbits, countbits); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + // These are the mappings of mprj_io GPIO pads that are set to + // specific functions on startup: + // + // JTAG = mgmt_gpio_io[0] (inout) + // SDO = mgmt_gpio_io[1] (output) + // SDI = mgmt_gpio_io[2] (input) + // CSB = mgmt_gpio_io[3] (input) + // SCK = mgmt_gpio_io[4] (input) + // ser_rx = mgmt_gpio_io[5] (input) + // ser_tx = mgmt_gpio_io[6] (output) + // irq = mgmt_gpio_io[7] (input) + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("timer.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/timer2/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/timer2/Makefile new file mode 100644 index 0000000..0be97ef --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/timer2/Makefile
@@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = timer2 + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/timer2/timer2.c b/verilog/dv/caravel/caravel/mgmt_soc/timer2/timer2.c new file mode 100644 index 0000000..6d598ac --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/timer2/timer2.c
@@ -0,0 +1,214 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +// -------------------------------------------------------- + +/* + * Timer2 Test --- This runs the same testbench as the + * other timer, on the 2nd counter/timer module instance. + */ + +void main() +{ + int i; + uint32_t value; + + /* Initialize output data vector to zero */ + reg_mprj_datah = 0x00000000; + reg_mprj_datal = 0x00000000; + + /* Apply all 38 bits to management standard output. */ + + /* The lower 32 will be used to output the count value */ + /* from the timer. The top 5 bits will be used to mark */ + /* specific checkpoints for the testbench simulation. */ + + reg_mprj_io_37 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_36 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_35 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_34 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_33 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_32 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_15 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_MGMT_STD_OUTPUT; + // reg_mprj_io_3 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_MGMT_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + /* Present start marker (see testbench verilog) */ + reg_mprj_datah = 0x0a; + + /* Configure timer for a single-shot countdown */ + reg_timer1_value = 0xdcba9876; + + /* Timer configuration bits: */ + /* 0 = timer enable (1 = enabled, 0 = disabled) */ + /* 1 = one-shot mode (1 = oneshot, 0 = continuous) */ + /* 2 = up/down (1 = count up, 0 = count down) */ + /* 3 = IRQ enable (1 = enabled, 0 = disabled) */ + + reg_timer1_config = 3; /* Enabled, one-shot, down count */ + + for (i = 0; i < 8; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_timer1_config = 0; /* Disabled */ + + reg_mprj_datah = 0x01; /* Check value in testbench */ + + reg_timer1_value = 0x00000011; + reg_timer1_config = 7; /* Enabled, one-shot, count up */ + + for (i = 0; i < 3; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x02; /* Check value in testbench */ + + reg_timer1_data = 0x00000101; // Set value (will be reset) + reg_timer1_config = 2; /* Disabled, one-shot, count up */ + reg_timer1_config = 5; /* Enabled, continuous, count down */ + + for (i = 0; i < 5; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x03; /* Check value in testbench */ + + reg_timer1_data = 0x00000145; // Force new value + + reg_mprj_datah = 0x04; /* Check value in testbench */ + + for (i = 0; i < 5; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x05; /* Check value in testbench */ + + /* Now, set up chained 64 bit timer. Check count-up */ + /* value and count-down value crossing the 32-bit */ + /* boundary. */ + + /* First disable both counters, and set the "chained" */ + /* property so that enable/disable will be synchronized */ + + reg_timer1_config = 8; /* Disabled, chained */ + reg_timer0_config = 8; /* Disabled, chained */ + + /* Configure timer for a chained single-shot countdown. */ + /* Count start = 0x0000000100001000, end = 0x0 */ + + reg_timer1_value = 0x00000055; + reg_timer0_value = 0x00001000; + + /* Timer configuration bits: */ + /* 0 = timer enable (1 = enabled, 0 = disabled) */ + /* 1 = one-shot mode (1 = oneshot, 0 = continuous) */ + /* 2 = up/down (1 = count up, 0 = count down) */ + /* 3 = chain (1 = enabled, 0 = disabled) */ + /* 4 = IRQ enable (1 = enabled, 0 = disabled) */ + + reg_timer1_config = 11; /* Enabled, one-shot, down count, chained */ + reg_timer0_config = 11; /* Enabled, one-shot, down count, chained */ + + for (i = 0; i < 1; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x06; /* Check value in testbench */ + + // Skip to the end. . . + reg_timer1_data = 0x00000000; + reg_timer0_data = 0x00000200; + + for (i = 0; i < 4; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x07; /* Check value in testbench */ + + reg_timer1_config = 14; /* Disabled, one-shot, up count, chained */ + reg_timer0_config = 14; /* Disabled, one-shot, up count, chained */ + + reg_timer1_value = 0x00000002; + reg_timer0_value = 0x00000000; + + reg_timer1_config = 15; /* Enabled, one-shot, up count, chained */ + reg_timer0_config = 15; /* Enabled, one-shot, up count, chained */ + + for (i = 0; i < 1; i++) { + value = reg_timer0_data; + reg_mprj_datal = value; // Put count value on GPIO + } + + reg_mprj_datah = 0x08; /* Check value in testbench */ + + // Skip to the end. . . + /* Count 0x00000001ffffff00 to 0x0000000200000000 and stop */ + + reg_timer1_data = 0x00000001; // Set value (will be reset) + reg_timer0_data = 0xffffff00; // Set value (will be reset) + + for (i = 0; i < 4; i++) { + value = reg_timer1_data; + reg_mprj_datal = value; // Put timer1 count value on GPIO + } + + /* Present end marker (see testbench verilog) */ + reg_mprj_datah = 0x10; +} +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/timer2/timer2_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/timer2/timer2_tb.v new file mode 100644 index 0000000..96aab4e --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/timer2/timer2_tb.v
@@ -0,0 +1,225 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module timer2_tb; + + reg clock; + reg RSTB; + reg power1, power2; + + always #10 clock <= (clock === 1'b0); + + initial begin + clock <= 0; + end + + initial begin + $dumpfile("timer2.vcd"); + $dumpvars(0, timer2_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (60) begin + repeat (1000) @(posedge clock); + $display("+1000 cycles"); + end + $display("%c[1;31m",27); + `ifdef GL + $display ("Monitor: Timeout, Test Timer2 (GL) Failed"); + `else + $display ("Monitor: Timeout, Test Timer2 (RTL) Failed"); + `endif + $display("%c[0m",27); + $finish; + end + + wire [37:0] mprj_io; // Most of these are no-connects + wire [5:0] checkbits; + wire [31:0] countbits; + + assign checkbits = mprj_io[37:32]; + assign countbits = mprj_io[31:0]; + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire gpio; + + // Monitor + initial begin + wait(checkbits == 6'h0a); + `ifdef GL + $display("Monitor: Test Timer2 (GL) Started"); + `else + $display("Monitor: Test Timer2 (RTL) Started"); + `endif + /* Add checks here */ + wait(checkbits == 6'h01); + $display(" countbits = 0x%x (should be 0xdcba7cfb)", countbits); + if(countbits !== 32'hdcba7cfb) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h02); + $display(" countbits = 0x%x (should be 0x19)", countbits); + if(countbits !== 32'h19) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h03); + $display(" countbits = %x (should be 0x0f)", countbits); + if(countbits !== 32'h0f) begin + $display("Monitor: Test Timer (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h04); + $display(" countbits = %x (should be 0x0f)", countbits); + if(countbits !== 32'h0f) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + wait(checkbits == 6'h05); + $display(" countbits = %x (should be 0x12bc)", countbits); + if(countbits !== 32'h12bc) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h06); + $display(" countbits = %x (should be 0x005d)", countbits); + if(countbits !== 32'h005d) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h07); + $display(" countbits = %x (should be 0x0008)", countbits); + if(countbits !== 32'h0008) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h08); + $display(" countbits = %x (should be 0x0259)", countbits); + if(countbits !== 32'h0259) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + wait(checkbits == 6'h10); + $display(" countbits = %x (should be 0x000a)", countbits); + if(countbits !== 32'h000a) begin + $display("Monitor: Test Timer2 (RTL) Failed"); + $finish; + end + + `ifdef GL + $display("Monitor: Test Timer2 (GL) Passed"); + `else + $display("Monitor: Test Timer2 (RTL) Passed"); + `endif + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + #1 $display("Timer state = %b (%d)", countbits, countbits); + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + // These are the mappings of mprj_io GPIO pads that are set to + // specific functions on startup: + // + // JTAG = mgmt_gpio_io[0] (inout) + // SDO = mgmt_gpio_io[1] (output) + // SDI = mgmt_gpio_io[2] (input) + // CSB = mgmt_gpio_io[3] (input) + // SCK = mgmt_gpio_io[4] (input) + // ser_rx = mgmt_gpio_io[5] (input) + // ser_tx = mgmt_gpio_io[6] (output) + // irq = mgmt_gpio_io[7] (input) + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("timer2.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/uart/Makefile b/verilog/dv/caravel/caravel/mgmt_soc/uart/Makefile new file mode 100644 index 0000000..e446947 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/uart/Makefile
@@ -0,0 +1,69 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# ---- Test patterns for project striVe ---- +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = uart + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all +
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/uart/uart.c b/verilog/dv/caravel/caravel/mgmt_soc/uart/uart.c new file mode 100644 index 0000000..13cee0f --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/uart/uart.c
@@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" +#include "../../stub.c" + +// -------------------------------------------------------- + +void main() +{ + int j; + + // Configure I/O: High 16 bits of user area used for a 16-bit + // word to write and be detected by the testbench verilog. + // Only serial Tx line is used in this testbench. It connects + // to mprj_io[6]. Since all lines of the chip are input or + // high impedence on startup, the I/O has to be configured + // for output + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Set clock to 64 kbaud and enable the UART. It is important to do this + // before applying the configuration, or else the Tx line initializes as + // zero, which indicates the start of a byte to the receiver. + + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + // Now, apply the configuration + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Start test + reg_mprj_datal = 0xa0000000; + + // This should appear at the output, received by the testbench UART. + // (Makes simulation time long.) + print("Monitor: Test UART (RTL) passed\n"); + + // Allow transmission to complete before signalling that the program + // has ended. + for (j = 0; j < 20; j++); + reg_mprj_datal = 0xab000000; +}
diff --git a/verilog/dv/caravel/caravel/mgmt_soc/uart/uart_tb.v b/verilog/dv/caravel/caravel/mgmt_soc/uart/uart_tb.v new file mode 100644 index 0000000..298e882 --- /dev/null +++ b/verilog/dv/caravel/caravel/mgmt_soc/uart/uart_tb.v
@@ -0,0 +1,146 @@ +`default_nettype none +/* + * StriVe - A full example SoC using PicoRV32 in SkyWater s8 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * Copyright (C) 2018 Tim Edwards <tim@efabless.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" +`include "tbuart.v" + +module uart_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + wire [37:0] mprj_io; + wire [15:0] checkbits; + wire uart_tx; + wire SDO; + + assign checkbits = mprj_io[31:16]; + assign uart_tx = mprj_io[6]; + + always #12.5 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("uart.vcd"); + $dumpvars(0, uart_tb); + + $display("Wait for UART o/p"); + repeat (150) begin + repeat (10000) @(posedge clock); + // Diagnostic. . . interrupts output pattern. + end + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + always @(checkbits) begin + if(checkbits == 16'hA000) begin + $display("UART Test started"); + end + else if(checkbits == 16'hAB00) begin + `ifdef GL + $display("UART Test (GL) passed"); + `else + $display("UART Test (RTL) passed"); + `endif + $finish; + end + end + + wire VDD3V3; + wire VDD1V8; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + assign mprj_io[3] = 1'b1; // Force CSB high. + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("uart.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + + // Testbench UART + tbuart tbuart ( + .ser_rx(uart_tx) + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/sections.lds b/verilog/dv/caravel/caravel/sections.lds new file mode 100644 index 0000000..8da9aae --- /dev/null +++ b/verilog/dv/caravel/caravel/sections.lds
@@ -0,0 +1,58 @@ +MEMORY { + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x400000 /* 4MB */ + RAM(xrw) : ORIGIN = 0x00000000, LENGTH = 0x0400 /* 256 words (1 KB) */ +} + +SECTIONS { + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + *(.srodata) /* .srodata sections (constants, strings, etc.) */ + *(.srodata*) /* .srodata*sections (constants, strings, etc.) */ + . = ALIGN(4); + _etext = .; /* define a global symbol at end of code */ + _sidata = _etext; /* This is used by the startup to initialize data */ + } >FLASH + + /* Initialized data section */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; + _ram_start = .; + . = ALIGN(4); + *(.data) + *(.data*) + *(.sdata) + *(.sdata*) + . = ALIGN(4); + _edata = .; + } >RAM + + /* Uninitialized data section */ + .bss : + { + . = ALIGN(4); + _sbss = .; + *(.bss) + *(.bss*) + *(.sbss) + *(.sbss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; + } >RAM + + /* Define the start of the heap */ + .heap : + { + . = ALIGN(4); + _heap_start = .; + } >RAM +}
diff --git a/verilog/dv/caravel/caravel/spiflash.v b/verilog/dv/caravel/caravel/spiflash.v new file mode 100644 index 0000000..d4a82d9 --- /dev/null +++ b/verilog/dv/caravel/caravel/spiflash.v
@@ -0,0 +1,414 @@ +`default_nettype none +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +// +// Simple SPI flash simulation model +// +// This model samples io input signals 1ns before the SPI clock edge and +// updates output signals 1ns after the SPI clock edge. +// +// Supported commands: +// AB, B9, FF, 03, BB, EB, ED +// +// Well written SPI flash data sheets: +// Cypress S25FL064L http://www.cypress.com/file/316661/download +// Cypress S25FL128L http://www.cypress.com/file/316171/download +// + +module spiflash #( + parameter FILENAME = "firmware.hex" +)( + input csb, + input clk, + inout io0, // MOSI + inout io1, // MISO + inout io2, + inout io3 +); + localparam verbose = 0; + localparam integer latency = 8; + + reg [7:0] buffer; + integer bitcount = 0; + integer bytecount = 0; + integer dummycount = 0; + + reg [7:0] spi_cmd; + reg [7:0] xip_cmd = 0; + reg [23:0] spi_addr; + + reg [7:0] spi_in; + reg [7:0] spi_out; + reg spi_io_vld; + + reg powered_up = 0; + + localparam [3:0] mode_spi = 1; + localparam [3:0] mode_dspi_rd = 2; + localparam [3:0] mode_dspi_wr = 3; + localparam [3:0] mode_qspi_rd = 4; + localparam [3:0] mode_qspi_wr = 5; + localparam [3:0] mode_qspi_ddr_rd = 6; + localparam [3:0] mode_qspi_ddr_wr = 7; + + reg [3:0] mode = 0; + reg [3:0] next_mode = 0; + + reg io0_oe = 0; + reg io1_oe = 0; + reg io2_oe = 0; + reg io3_oe = 0; + + reg io0_dout = 0; + reg io1_dout = 0; + reg io2_dout = 0; + reg io3_dout = 0; + + assign #1 io0 = io0_oe ? io0_dout : 1'bz; + assign #1 io1 = io1_oe ? io1_dout : 1'bz; + assign #1 io2 = io2_oe ? io2_dout : 1'bz; + assign #1 io3 = io3_oe ? io3_dout : 1'bz; + + wire io0_delayed; + wire io1_delayed; + wire io2_delayed; + wire io3_delayed; + + assign #1 io0_delayed = io0; + assign #1 io1_delayed = io1; + assign #1 io2_delayed = io2; + assign #1 io3_delayed = io3; + + // 16 MB (128Mb) Flash + reg [7:0] memory [0:16*1024*1024-1]; + + initial begin + $display("Memory 5 bytes = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + memory[1048576], memory[1048577], memory[1048578], + memory[1048579], memory[1048580]); + $display("Reading %s", FILENAME); + $readmemh(FILENAME, memory); + $display("%s loaded into memory", FILENAME); + $display("Memory 5 bytes = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + memory[1048576], memory[1048577], memory[1048578], + memory[1048579], memory[1048580]); + end + + task spi_action; + begin + spi_in = buffer; + + if (bytecount == 1) begin + spi_cmd = buffer; + + if (spi_cmd == 8'h ab) + powered_up = 1; + + if (spi_cmd == 8'h b9) + powered_up = 0; + + if (spi_cmd == 8'h ff) + xip_cmd = 0; + end + + if (powered_up && spi_cmd == 'h 03) begin + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) + spi_addr[7:0] = buffer; + + if (bytecount >= 4) begin + buffer = memory[spi_addr]; + spi_addr = spi_addr + 1; + end + end + + if (powered_up && spi_cmd == 'h bb) begin + if (bytecount == 1) + mode = mode_dspi_rd; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) + spi_addr[7:0] = buffer; + + if (bytecount == 5) begin + xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00; + mode = mode_dspi_wr; + dummycount = latency; + end + + if (bytecount >= 5) begin + buffer = memory[spi_addr]; + spi_addr = spi_addr + 1; + end + end + + if (powered_up && spi_cmd == 'h eb) begin + if (bytecount == 1) + mode = mode_qspi_rd; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) + spi_addr[7:0] = buffer; + + if (bytecount == 5) begin + xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00; + mode = mode_qspi_wr; + dummycount = latency; + end + + if (bytecount >= 5) begin + buffer = memory[spi_addr]; + spi_addr = spi_addr + 1; + end + end + + if (powered_up && spi_cmd == 'h ed) begin + if (bytecount == 1) + next_mode = mode_qspi_ddr_rd; + + if (bytecount == 2) + spi_addr[23:16] = buffer; + + if (bytecount == 3) + spi_addr[15:8] = buffer; + + if (bytecount == 4) + spi_addr[7:0] = buffer; + + if (bytecount == 5) begin + xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00; + mode = mode_qspi_ddr_wr; + dummycount = latency; + end + + if (bytecount >= 5) begin + buffer = memory[spi_addr]; + spi_addr = spi_addr + 1; + end + end + + spi_out = buffer; + spi_io_vld = 1; + + if (verbose) begin + if (bytecount == 1) + $write("<SPI-START>"); + $write("<SPI:%02x:%02x>", spi_in, spi_out); + end + + end + endtask + + task ddr_rd_edge; + begin + buffer = {buffer, io3_delayed, io2_delayed, io1_delayed, io0_delayed}; + bitcount = bitcount + 4; + if (bitcount == 8) begin + bitcount = 0; + bytecount = bytecount + 1; + spi_action; + end + end + endtask + + task ddr_wr_edge; + begin + io0_oe = 1; + io1_oe = 1; + io2_oe = 1; + io3_oe = 1; + + io0_dout = buffer[4]; + io1_dout = buffer[5]; + io2_dout = buffer[6]; + io3_dout = buffer[7]; + + buffer = {buffer, 4'h 0}; + bitcount = bitcount + 4; + if (bitcount == 8) begin + bitcount = 0; + bytecount = bytecount + 1; + spi_action; + end + end + endtask + + always @(csb) begin + if (csb) begin + if (verbose) begin + $display(""); + $fflush; + end + buffer = 0; + bitcount = 0; + bytecount = 0; + mode = mode_spi; + io0_oe = 0; + io1_oe = 0; + io2_oe = 0; + io3_oe = 0; + end else + if (xip_cmd) begin + buffer = xip_cmd; + bitcount = 0; + bytecount = 1; + spi_action; + end + end + + always @(csb, clk) begin + spi_io_vld = 0; + if (!csb && !clk) begin + if (dummycount > 0) begin + io0_oe = 0; + io1_oe = 0; + io2_oe = 0; + io3_oe = 0; + end else + case (mode) + mode_spi: begin + io0_oe = 0; + io1_oe = 1; + io2_oe = 0; + io3_oe = 0; + io1_dout = buffer[7]; + end + mode_dspi_rd: begin + io0_oe = 0; + io1_oe = 0; + io2_oe = 0; + io3_oe = 0; + end + mode_dspi_wr: begin + io0_oe = 1; + io1_oe = 1; + io2_oe = 0; + io3_oe = 0; + io0_dout = buffer[6]; + io1_dout = buffer[7]; + end + mode_qspi_rd: begin + io0_oe = 0; + io1_oe = 0; + io2_oe = 0; + io3_oe = 0; + end + mode_qspi_wr: begin + io0_oe = 1; + io1_oe = 1; + io2_oe = 1; + io3_oe = 1; + io0_dout = buffer[4]; + io1_dout = buffer[5]; + io2_dout = buffer[6]; + io3_dout = buffer[7]; + end + mode_qspi_ddr_rd: begin + ddr_rd_edge; + end + mode_qspi_ddr_wr: begin + ddr_wr_edge; + end + endcase + if (next_mode) begin + case (next_mode) + mode_qspi_ddr_rd: begin + io0_oe = 0; + io1_oe = 0; + io2_oe = 0; + io3_oe = 0; + end + mode_qspi_ddr_wr: begin + io0_oe = 1; + io1_oe = 1; + io2_oe = 1; + io3_oe = 1; + io0_dout = buffer[4]; + io1_dout = buffer[5]; + io2_dout = buffer[6]; + io3_dout = buffer[7]; + end + endcase + mode = next_mode; + next_mode = 0; + end + end + end + + always @(posedge clk) begin + if (!csb) begin + if (dummycount > 0) begin + dummycount = dummycount - 1; + end else + case (mode) + mode_spi: begin + buffer = {buffer, io0}; + bitcount = bitcount + 1; + if (bitcount == 8) begin + bitcount = 0; + bytecount = bytecount + 1; + spi_action; + end + end + mode_dspi_rd, mode_dspi_wr: begin + buffer = {buffer, io1, io0}; + bitcount = bitcount + 2; + if (bitcount == 8) begin + bitcount = 0; + bytecount = bytecount + 1; + spi_action; + end + end + mode_qspi_rd, mode_qspi_wr: begin + buffer = {buffer, io3, io2, io1, io0}; + bitcount = bitcount + 4; + if (bitcount == 8) begin + bitcount = 0; + bytecount = bytecount + 1; + spi_action; + end + end + mode_qspi_ddr_rd: begin + ddr_rd_edge; + end + mode_qspi_ddr_wr: begin + ddr_wr_edge; + end + endcase + end + end +endmodule
diff --git a/verilog/dv/caravel/caravel/start.s b/verilog/dv/caravel/caravel/start.s new file mode 100644 index 0000000..62a6f42 --- /dev/null +++ b/verilog/dv/caravel/caravel/start.s
@@ -0,0 +1,159 @@ +.section .text + +start: + +# zero-initialize register file +addi x1, zero, 0 +# x2 (sp) is initialized by reset +addi x3, zero, 0 +addi x4, zero, 0 +addi x5, zero, 0 +addi x6, zero, 0 +addi x7, zero, 0 +addi x8, zero, 0 +addi x9, zero, 0 +addi x10, zero, 0 +addi x11, zero, 0 +addi x12, zero, 0 +addi x13, zero, 0 +addi x14, zero, 0 +addi x15, zero, 0 +addi x16, zero, 0 +addi x17, zero, 0 +addi x18, zero, 0 +addi x19, zero, 0 +addi x20, zero, 0 +addi x21, zero, 0 +addi x22, zero, 0 +addi x23, zero, 0 +addi x24, zero, 0 +addi x25, zero, 0 +addi x26, zero, 0 +addi x27, zero, 0 +addi x28, zero, 0 +addi x29, zero, 0 +addi x30, zero, 0 +addi x31, zero, 0 + +# zero initialize scratchpad memory +# setmemloop: +# sw zero, 0(x1) +# addi x1, x1, 4 +# blt x1, sp, setmemloop + +# copy data section +la a0, _sidata +la a1, _sdata +la a2, _edata +bge a1, a2, end_init_data +loop_init_data: +lw a3, 0(a0) +sw a3, 0(a1) +addi a0, a0, 4 +addi a1, a1, 4 +blt a1, a2, loop_init_data +end_init_data: + +# zero-init bss section +la a0, _sbss +la a1, _ebss +bge a0, a1, end_init_bss +loop_init_bss: +sw zero, 0(a0) +addi a0, a0, 4 +blt a0, a1, loop_init_bss +end_init_bss: + +# call main +call main +loop: +j loop + +.global flashio_worker_begin +.global flashio_worker_end + +.balign 4 + +flashio_worker_begin: +# a0 ... data pointer +# a1 ... data length +# a2 ... optional WREN cmd (0 = disable) + +# address of SPI ctrl reg +li t0, 0x28000000 + +# Set CS high, IO0 is output +li t1, 0x120 +sh t1, 0(t0) + +# Enable Manual SPI Ctrl +sb zero, 3(t0) + +# Send optional WREN cmd +beqz a2, flashio_worker_L1 +li t5, 8 +andi t2, a2, 0xff +flashio_worker_L4: +srli t4, t2, 7 +sb t4, 0(t0) +ori t4, t4, 0x10 +sb t4, 0(t0) +slli t2, t2, 1 +andi t2, t2, 0xff +addi t5, t5, -1 +bnez t5, flashio_worker_L4 +sb t1, 0(t0) + +# SPI transfer +flashio_worker_L1: + +# If byte count is zero, we're done +beqz a1, flashio_worker_L3 + +# Set t5 to count down 32 bits +li t5, 32 +# Load t2 from address a0 (4 bytes) +lw t2, 0(a0) + +flashio_worker_LY: +# Set t6 to count down 8 bits +li t6, 8 + +flashio_worker_L2: +# Clock out the bit (msb first) on IO0 and read bit in from IO1 +srli t4, t2, 31 +sb t4, 0(t0) +ori t4, t4, 0x10 +sb t4, 0(t0) +lbu t4, 0(t0) +andi t4, t4, 2 +srli t4, t4, 1 +slli t2, t2, 1 +or t2, t2, t4 + +# Decrement 32 bit count +addi t5, t5, -1 +bnez t5, flashio_worker_LX + +sw t2, 0(a0) +addi a0, a0, 4 +lw t2, 0(a0) + +flashio_worker_LX: +addi t6, t6, -1 +bnez t6, flashio_worker_L2 +addi a1, a1, -1 +bnez a1, flashio_worker_LY + +beqz t5, flashio_worker_L3 +sw t2, 0(a0) + +flashio_worker_L3: +# Back to MEMIO mode +li t1, 0x80 +sb t1, 3(t0) + +ret +.balign 4 +flashio_worker_end: +
diff --git a/verilog/dv/caravel/caravel/stub.c b/verilog/dv/caravel/caravel/stub.c new file mode 100644 index 0000000..575cfc3 --- /dev/null +++ b/verilog/dv/caravel/caravel/stub.c
@@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +void putchar(char c) +{ + if (c == '\n') + putchar('\r'); + reg_uart_data = c; +} + +void print(const char *p) +{ + while (*p) + putchar(*(p++)); +} \ No newline at end of file
diff --git a/verilog/dv/caravel/caravel/tbuart.v b/verilog/dv/caravel/caravel/tbuart.v new file mode 100644 index 0000000..f623a60 --- /dev/null +++ b/verilog/dv/caravel/caravel/tbuart.v
@@ -0,0 +1,90 @@ +`default_nettype none +/* + * PicoSoC - A simple example SoC using PicoRV32 + * + * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +`timescale 1 ns / 1 ps + +/* tbuart --- mimic an external UART display, operating at 9600 baud */ +/* and accepting ASCII characters for display. */ + +/* To do: Match a known UART 3.3V 16x2 LCD display. However, it */ +/* should be possible on a testing system to interface to the UART */ +/* pins on a Raspberry Pi, also running at 3.3V. */ + +module tbuart ( + input ser_rx +); + reg [3:0] recv_state; + reg [2:0] recv_divcnt; + reg [7:0] recv_pattern; + reg [8*50-1:0] recv_buf_data; // 50 characters. Increase as needed for tests. + + reg clk; + + initial begin + clk <= 1'b0; + recv_state <= 0; + recv_divcnt <= 0; + recv_pattern <= 0; + recv_buf_data <= 0; + end + + // NOTE: Running at 3.0us clock period @ 5 clocks per bit = 15.0us per + // bit ~= 64 kbaud. Not tuned to any particular UART. Most run at + // 9600 baud default and will bounce up to higher baud rates when + // passed specific command words. + + always #1500 clk <= (clk === 1'b0); + + always @(posedge clk) begin + recv_divcnt <= recv_divcnt + 1; + case (recv_state) + 0: begin + if (!ser_rx) + recv_state <= 1; + recv_divcnt <= 0; + end + 1: begin + if (2*recv_divcnt > 3'd3) begin + recv_state <= 2; + recv_divcnt <= 0; + end + end + 10: begin + if (recv_divcnt > 3'd3) begin + // 0x0a = '\n' + if (recv_pattern == 8'h0a) begin + $display("output: %s", recv_buf_data); + end else begin + recv_buf_data <= {recv_buf_data, recv_pattern}; + end + recv_state <= 0; + end + end + default: begin + if (recv_divcnt > 3'd3) begin + recv_pattern <= {ser_rx, recv_pattern[7:1]}; + recv_state <= recv_state + 1; + recv_divcnt <= 0; + end + end + endcase + end + +endmodule
diff --git a/verilog/dv/caravel/caravel/user_proj_example/Makefile b/verilog/dv/caravel/caravel/user_proj_example/Makefile new file mode 100644 index 0000000..7e37e02 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/Makefile
@@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# ---- Test patterns for project striVe ---- + +.SUFFIXES: +.SILENT: clean all + +PATTERNS = io_ports la_test1 la_test2 + +all: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make -f Makefile $${i}.vcd &> verify.log && grep Monitor verify.log) ; \ + done + +clean: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make clean ) ; \ + done + +.PHONY: clean all
diff --git a/verilog/dv/caravel/caravel/user_proj_example/README.md b/verilog/dv/caravel/caravel/user_proj_example/README.md new file mode 100644 index 0000000..503b8f4 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/README.md
@@ -0,0 +1,37 @@ +<!--- +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +--> +# Mega-Project Counter Tests + +The directory includes three tests for the counter mega-project example: + +1) IO Ports Test: + + * Configures the user space lower 8 IO pins as outputs + * Observes the counter value through the configured pins in the testbench + + 2) Logic Analyzer Test 1: + + * Configures LA probes [31:0] as inputs to the management SoC to monitor the counter value + * Configures LA probes [63:32] as outputs from the management SoC to set the counter initial value + * Flags when counter value exceeds 500 through the management SoC gpio + * Outputs message to the UART when the test concludes successfuly + + 3) Logic Analyzer Test 2: + + * Configures LA probes [64] and [65] as outputs from the management SoC to set counter clock and reset values + * Provides counter clock and monitors the counter value after five clock cycles
diff --git a/verilog/dv/caravel/caravel/user_proj_example/io_ports/Makefile b/verilog/dv/caravel/caravel/user_proj_example/io_ports/Makefile new file mode 100644 index 0000000..d6c2bf6 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/io_ports/Makefile
@@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +VERILOG_PATH = ../../../.. +RTL_PATH = $(VERILOG_PATH)/rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = io_ports + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all
diff --git a/verilog/dv/caravel/caravel/user_proj_example/io_ports/io_ports.c b/verilog/dv/caravel/caravel/user_proj_example/io_ports/io_ports.c new file mode 100644 index 0000000..a159f0a --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/io_ports/io_ports.c
@@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" + +/* + IO Test: + - Configures MPRJ lower 8-IO pins as outputs + - Observes counter value through the MPRJ lower 8 IO pins (in the testbench) +*/ + +void main() +{ + /* + IO Control Registers + | DM | VTRIP | SLOW | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN | + | 3-bits | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | + + Output: 0000_0110_0000_1110 (0x1808) = GPIO_MODE_USER_STD_OUTPUT + | DM | VTRIP | SLOW | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN | + | 110 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | + + + Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL + | DM | VTRIP | SLOW | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN | + | 001 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | + + */ + + // Configure lower 8-IOs as user output + // Observe counter value in the testbench + reg_mprj_io_0 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_3 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_6 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_USER_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + +} +
diff --git a/verilog/dv/caravel/caravel/user_proj_example/io_ports/io_ports_tb.v b/verilog/dv/caravel/caravel/user_proj_example/io_ports/io_ports_tb.v new file mode 100644 index 0000000..c680a0b --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/io_ports/io_ports_tb.v
@@ -0,0 +1,152 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module io_ports_tb; + reg clock; + reg RSTB; + reg power1, power2; + reg power3, power4; + + wire gpio; + wire [37:0] mprj_io; + wire [7:0] mprj_io_0; + + assign mprj_io_0 = mprj_io[7:0]; + + // External clock is used by default. Make this artificially fast for the + // simulation. Normally this would be a slow clock and the digital PLL + // would be the fast clock. + + always #12.5 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("io_ports.vcd"); + $dumpvars(0, io_ports_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (25) begin + repeat (1000) @(posedge clock); + // $display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + initial begin + // Observe Output pins [7:0] + wait(mprj_io_0 == 8'h01); + wait(mprj_io_0 == 8'h02); + wait(mprj_io_0 == 8'h03); + wait(mprj_io_0 == 8'h04); + wait(mprj_io_0 == 8'h05); + wait(mprj_io_0 == 8'h06); + wait(mprj_io_0 == 8'h07); + wait(mprj_io_0 == 8'h08); + wait(mprj_io_0 == 8'h09); + wait(mprj_io_0 == 8'h0A); + wait(mprj_io_0 == 8'hFF); + wait(mprj_io_0 == 8'h00); + + $display("Monitor: Test 1 Mega-Project IO (RTL) Passed"); + $finish; + end + + initial begin + RSTB <= 1'b0; + #2000; + RSTB <= 1'b1; // Release reset + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + power3 <= 1'b0; + power4 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + #200; + power3 <= 1'b1; + #200; + power4 <= 1'b1; + end + + always @(mprj_io) begin + #1 $display("MPRJ-IO state = %b ", mprj_io[7:0]); + end + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + wire VDD3V3 = power1; + wire VDD1V8 = power2; + wire USER_VDD3V3 = power3; + wire USER_VDD1V8 = power4; + wire VSS = 1'b0; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (USER_VDD3V3), + .vdda2 (USER_VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (USER_VDD1V8), + .vccd2 (USER_VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("io_ports.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/user_proj_example/la_test1/Makefile b/verilog/dv/caravel/caravel/user_proj_example/la_test1/Makefile new file mode 100644 index 0000000..968a74b --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/la_test1/Makefile
@@ -0,0 +1,66 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +RTL_PATH = ../../../../rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = la_test1 + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all
diff --git a/verilog/dv/caravel/caravel/user_proj_example/la_test1/la_test1.c b/verilog/dv/caravel/caravel/user_proj_example/la_test1/la_test1.c new file mode 100644 index 0000000..9759ed7 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/la_test1/la_test1.c
@@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" +#include "../../stub.c" + +// -------------------------------------------------------- + +/* + MPRJ Logic Analyzer Test: + - Observes counter value through LA probes [31:0] + - Sets counter initial value through LA probes [63:32] + - Flags when counter value exceeds 500 through the management SoC gpio + - Outputs message to the UART when the test concludes successfuly +*/ + +void main() +{ + // The upper GPIO pins are configured to be output + // and accessble to the management SoC. + // Used to flad the start/end of a test + // The lower GPIO pins are configured to be output + // and accessible to the user project. They show + // the project count value, although this test is + // designed to read the project count through the + // logic analyzer probes. + // I/O 6 is configured for the UART Tx line + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_15 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_3 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_USER_STD_OUTPUT; + + reg_mprj_io_6 = GPIO_MODE_MGMT_STD_OUTPUT; + + // Set UART clock to 64 kbaud (enable before I/O configuration) + reg_uart_clkdiv = 625; + reg_uart_enable = 1; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Configure LA probes [31:0], [127:64] as inputs to the cpu + // Configure LA probes [63:32] as outputs from the cpu + reg_la0_ena = 0xFFFFFFFF; // [31:0] + reg_la1_ena = 0x00000000; // [63:32] + reg_la2_ena = 0xFFFFFFFF; // [95:64] + reg_la3_ena = 0xFFFFFFFF; // [127:96] + + // Flag start of the test + reg_mprj_datal = 0xAB400000; + + // Set Counter value to zero through LA probes [63:32] + reg_la1_data = 0x00000000; + + // Configure LA probes from [63:32] as inputs to disable counter write + reg_la1_ena = 0xFFFFFFFF; + + while (1) { + if (reg_la0_data > 0x1F4) { + reg_mprj_datal = 0xAB410000; + break; + } + } + print("\n"); + print("Monitor: Test 2 Passed\n\n"); // Makes simulation very long! + reg_mprj_datal = 0xAB510000; +} +
diff --git a/verilog/dv/caravel/caravel/user_proj_example/la_test1/la_test1_tb.v b/verilog/dv/caravel/caravel/user_proj_example/la_test1/la_test1_tb.v new file mode 100644 index 0000000..210098f --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/la_test1/la_test1_tb.v
@@ -0,0 +1,138 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" +`include "tbuart.v" + +module la_test1_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire uart_tx; + wire [37:0] mprj_io; + wire [15:0] checkbits; + + assign checkbits = mprj_io[31:16]; + assign uart_tx = mprj_io[6]; + + always #12.5 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("la_test1.vcd"); + $dumpvars(0, la_test1_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (200) begin + repeat (1000) @(posedge clock); + // $display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Mega-Project IO (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + initial begin + wait(checkbits == 16'hAB40); + $display("LA Test 1 started"); + wait(checkbits == 16'hAB41); + wait(checkbits == 16'hAB51); + #10000; + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + wire VDD1V8; + wire VDD3V3; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("la_test1.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), // not used + .io3() // not used + ); + + // Testbench UART + tbuart tbuart ( + .ser_rx(uart_tx) + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/caravel/caravel/user_proj_example/la_test2/Makefile b/verilog/dv/caravel/caravel/user_proj_example/la_test2/Makefile new file mode 100644 index 0000000..4980a08 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/la_test2/Makefile
@@ -0,0 +1,66 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FIRMWARE_PATH = ../.. +RTL_PATH = ../../../../rtl +IP_PATH = ../../../../ip +BEHAVIOURAL_MODELS = ../../ + +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv32-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +SIM?=RTL + +.SUFFIXES: + +PATTERN = la_test2 + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -DFUNCTIONAL -DSIM -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(BEHAVIOURAL_MODELS) \ + -I $(PDK_PATH) -I $(IP_PATH) -I $(RTL_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s + ${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all
diff --git a/verilog/dv/caravel/caravel/user_proj_example/la_test2/la_test2.c b/verilog/dv/caravel/caravel/user_proj_example/la_test2/la_test2.c new file mode 100644 index 0000000..0267d25 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/la_test2/la_test2.c
@@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2020 Efabless Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../../defs.h" +#include "../../stub.c" + +/* + MPRJ LA Test: + - Sets counter clk through LA[64] + - Sets counter rst through LA[65] + - Observes count value for five clk cycle through LA[31:0] +*/ + +int clk = 0; +int i; + +void main() +{ + // All GPIO pins are configured to be output + // Used to flad the start/end of a test + + reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_23 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_22 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_21 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_20 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_19 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_18 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_17 = GPIO_MODE_MGMT_STD_OUTPUT; + reg_mprj_io_16 = GPIO_MODE_MGMT_STD_OUTPUT; + + reg_mprj_io_15 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_14 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_13 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_12 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_11 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_10 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_9 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_8 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_7 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_5 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_4 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_3 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_2 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_1 = GPIO_MODE_USER_STD_OUTPUT; + reg_mprj_io_0 = GPIO_MODE_USER_STD_OUTPUT; + + /* Apply configuration */ + reg_mprj_xfer = 1; + while (reg_mprj_xfer == 1); + + // Configure All LA probes as inputs to the cpu + reg_la0_ena = 0xFFFFFFFF; // [31:0] + reg_la1_ena = 0xFFFFFFFF; // [63:32] + reg_la2_ena = 0xFFFFFFFF; // [95:64] + reg_la3_ena = 0xFFFFFFFF; // [127:96] + + // Flag start of the test + reg_mprj_datal = 0xAB600000; + + // Configure LA[64] LA[65] as outputs from the cpu + reg_la2_ena = 0xFFFFFFFC; + + // Set clk & reset to one + reg_la2_data = 0x00000003; + + // Toggle clk & de-assert reset + for (i=0; i<11; i=i+1) { + clk = !clk; + reg_la2_data = 0x00000000 | clk; + } + + if (reg_la0_data == 0x05) { + reg_mprj_datal = 0xAB610000; + } + +} +
diff --git a/verilog/dv/caravel/caravel/user_proj_example/la_test2/la_test2_tb.v b/verilog/dv/caravel/caravel/user_proj_example/la_test2/la_test2_tb.v new file mode 100644 index 0000000..b9e5c80 --- /dev/null +++ b/verilog/dv/caravel/caravel/user_proj_example/la_test2/la_test2_tb.v
@@ -0,0 +1,129 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "caravel.v" +`include "spiflash.v" + +module la_test2_tb; + reg clock; + reg RSTB; + reg power1, power2; + + wire gpio; + wire [37:0] mprj_io; + wire [15:0] checkbits; + + assign checkbits = mprj_io[31:16]; + + always #12.5 clock <= (clock === 1'b0); + + initial begin + clock = 0; + end + + initial begin + $dumpfile("la_test2.vcd"); + $dumpvars(0, la_test2_tb); + + // Repeat cycles of 1000 clock edges as needed to complete testbench + repeat (30) begin + repeat (1000) @(posedge clock); + // $display("+1000 cycles"); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Mega-Project IO (RTL) Failed"); + $display("%c[0m",27); + $finish; + end + + initial begin + wait(checkbits == 16'h AB60); + $display("Monitor: Test 2 MPRJ-Logic Analyzer Started"); + wait(checkbits == 16'h AB61); + $display("Monitor: Test 2 MPRJ-Logic Analyzer Passed"); + $finish; + end + + initial begin + RSTB <= 1'b0; + #1000; + RSTB <= 1'b1; // Release reset + #2000; + end + + initial begin // Power-up sequence + power1 <= 1'b0; + power2 <= 1'b0; + #200; + power1 <= 1'b1; + #200; + power2 <= 1'b1; + end + + wire flash_csb; + wire flash_clk; + wire flash_io0; + wire flash_io1; + + wire VDD1V8; + wire VDD3V3; + wire VSS; + + assign VDD3V3 = power1; + assign VDD1V8 = power2; + assign VSS = 1'b0; + + caravel uut ( + .vddio (VDD3V3), + .vssio (VSS), + .vdda (VDD3V3), + .vssa (VSS), + .vccd (VDD1V8), + .vssd (VSS), + .vdda1 (VDD3V3), + .vdda2 (VDD3V3), + .vssa1 (VSS), + .vssa2 (VSS), + .vccd1 (VDD1V8), + .vccd2 (VDD1V8), + .vssd1 (VSS), + .vssd2 (VSS), + .clock (clock), + .gpio (gpio), + .mprj_io (mprj_io), + .flash_csb(flash_csb), + .flash_clk(flash_clk), + .flash_io0(flash_io0), + .flash_io1(flash_io1), + .resetb (RSTB) + ); + + spiflash #( + .FILENAME("la_test2.hex") + ) spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(), + .io3() + ); + +endmodule +`default_nettype wire
diff --git a/verilog/dv/wb_utests/wb_utests/Makefile b/verilog/dv/wb_utests/wb_utests/Makefile new file mode 100644 index 0000000..9684dfc --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/Makefile
@@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +# ---- Test patterns for project striVe ---- + +.SUFFIXES: +.SILENT: clean all + +PATTERNS = gpio_wb intercon_wb la_wb mem_wb mprj_ctrl spi_sysctrl_wb spimemio_wb uart_wb + +all: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make -f Makefile $${i}.vcd &> verify.log && grep Monitor verify.log) ; \ + done + +clean: ${PATTERNS} + for i in ${PATTERNS}; do \ + ( cd $$i && make clean ) ; \ + done + +.PHONY: clean all
diff --git a/verilog/dv/wb_utests/wb_utests/gpio_wb/Makefile b/verilog/dv/wb_utests/wb_utests/gpio_wb/Makefile new file mode 100644 index 0000000..a42f609 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/gpio_wb/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = gpio_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd + +.PHONY: clean all
diff --git a/verilog/dv/wb_utests/wb_utests/gpio_wb/gpio_wb_tb.v b/verilog/dv/wb_utests/wb_utests/gpio_wb/gpio_wb_tb.v new file mode 100644 index 0000000..6ff214c --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/gpio_wb/gpio_wb_tb.v
@@ -0,0 +1,198 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`include "gpio_wb.v" + +module gpio_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + reg [15:0] gpio_in_pad; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + gpio_in_pad = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("gpio_wb_tb.vcd"); + $dumpvars(0, gpio_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test GPIO Wishbone Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + // GPIO Internal Register Addresses + wire [31:0] gpio_adr = uut.BASE_ADR | uut.GPIO_DATA; + wire [31:0] gpio_oeb_adr = uut.BASE_ADR | uut.GPIO_ENA; + wire [31:0] gpio_pu_adr = uut.BASE_ADR | uut.GPIO_PU; + wire [31:0] gpio_pd_adr = uut.BASE_ADR | uut.GPIO_PD; + + reg [15:0] gpio_data; + reg [15:0] gpio_pu; + reg [15:0] gpio_pd; + reg [15:0] gpio_oeb; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Write to gpio_data reg + gpio_in_pad = 16'h FFFF; + gpio_data = 16'h A000; + write(gpio_adr, gpio_data); + + #2; + // Read from gpio_data reg + read(gpio_adr); + if (wb_dat_o !== {gpio_data, gpio_in_pad}) begin + $display("Monitor: Error reading from gpio reg"); + $finish; + end + + #2; + // Write to pull-up reg + gpio_pu = 16'h 000f; + write(gpio_pu_adr, gpio_pu); + + #2; + // Read from pull-up reg + read(gpio_pu_adr); + if (wb_dat_o !== {16'd0, gpio_pu}) begin + $display("Monitor: Error reading from gpio pull-up reg"); + $finish; + end + + #2; + // Write to pull-down reg + gpio_pd = 16'h 00f0; + write(gpio_pd_adr, gpio_pd); + + #2; + // Read from pull-down reg + read(gpio_pd_adr); + if (wb_dat_o !== {16'd0, gpio_pd}) begin + $display("Monitor: Error reading from gpio pull-down reg"); + $finish; + end + + #2; + // Write to gpio enable reg + gpio_oeb = 16'h 00ff; + write(gpio_oeb_adr, gpio_oeb); + + #2; + // Read from gpio enable reg + read(gpio_oeb_adr); + if (wb_dat_o !== {16'd0, gpio_oeb}) begin + $display("Monitor: Error reading from gpio output enable reg"); + $finish; + end + + #6; + $display("Monitor: GPIO WB Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + gpio_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + .gpio_in_pad(gpio_in_pad) + ); + +endmodule
diff --git a/verilog/dv/wb_utests/wb_utests/intercon_wb/Makefile b/verilog/dv/wb_utests/wb_utests/intercon_wb/Makefile new file mode 100644 index 0000000..294cf17 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/intercon_wb/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = intercon_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb_utests/wb_utests/intercon_wb/intercon_wb_tb.v b/verilog/dv/wb_utests/wb_utests/intercon_wb/intercon_wb_tb.v new file mode 100644 index 0000000..5d91efa --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/intercon_wb/intercon_wb_tb.v
@@ -0,0 +1,203 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`include "wb_intercon.v" +`include "dummy_slave.v" + +`define AW 32 +`define DW 32 +`define NS 6 + +`define SLAVE_ADR { \ + {8'h28, {24{1'b0}} }, \ + {8'h23, {24{1'b0}} }, \ + {8'h21, {24{1'b0}} }, \ + {8'h20, {24{1'b0}} }, \ + {8'h10, {24{1'b0}} }, \ + {8'h00, {24{1'b0}} } \ +}\ + +`define ADR_MASK { \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} }, \ + {8'hFF, {24{1'b0}} } \ +}\ + +module intercon_wb_tb; + + localparam SEL = `DW / 8; + + reg wb_clk_i; + reg wb_rst_i; + + // Master Interface + reg wbm_stb_i; + reg wbm_cyc_i; + reg wbm_we_i; + reg [SEL-1:0] wbm_sel_i; + reg [`AW-1:0] wbm_adr_i; + reg [`DW-1:0] wbm_dat_i; + + wire [`DW-1:0] wbm_dat_o; + wire wbm_ack_o; + + // Wishbone Slave Interface + wire [`NS-1:0] wbs_stb_i; + wire [`NS-1:0] wbs_ack_o; + wire [(`NS*`DW)-1:0] wbs_adr_i; + wire [(`NS*`AW)-1:0] wbs_dat_i; + wire [(`NS*`DW)-1:0] wbs_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wbm_adr_i = 0; + wbm_dat_i = 0; + wbm_sel_i = 0; + wbm_we_i = 0; + wbm_cyc_i = 0; + wbm_stb_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("intercon_wb_tb.vcd"); + $dumpvars(0, intercon_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Wishbone Interconnect Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [`AW*`NS-1: 0] addr = `SLAVE_ADR; + reg [`DW:0] slave_data; + reg [`AW:0] slave_addr; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // W/R from all slaves + for (i=0; i<`NS; i=i+1) begin + slave_addr = addr[i*`AW +: `AW]; + slave_data = $urandom_range(0, 2**32); + write(slave_addr, slave_data); + #2; + read(slave_addr); + if (wbm_dat_o !== slave_data) begin + $display("%c[1;31m",27); + $display ("Monitor: Reading from slave %0d failed", i); + $display("Monitor: Test Wishbone Interconnect failed"); + $display("%c[0m",27); + $finish; + end + end + $display("Monitor: Test Wishbone Interconnect Success!"); + $finish; + end + + task write; + input [`AW-1:0] addr; + input [`AW-1:0] data; + begin + @(posedge wb_clk_i) begin + wbm_stb_i = 1; + wbm_cyc_i = 1; + wbm_sel_i = {SEL{1'b1}}; + wbm_we_i = 1; + wbm_adr_i = addr; + wbm_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wbm_ack_o == 1); + wait(wbm_ack_o == 0); + wbm_cyc_i = 0; + wbm_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [`AW-1:0] addr; + begin + @(posedge wb_clk_i) begin + wbm_stb_i = 1; + wbm_cyc_i = 1; + wbm_adr_i = addr; + wbm_we_i = 0; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wbm_ack_o == 1); + wait(wbm_ack_o == 0); + wbm_cyc_i = 0; + wbm_stb_i = 0; + $display("Read Cycle Ended."); + + end + endtask + + wb_intercon #( + .AW(`AW), + .DW(`DW), + .NS(`NS), + .ADR_MASK(`ADR_MASK), + .SLAVE_ADR(`SLAVE_ADR) + ) uut( + // Master Interface + .wbm_adr_i(wbm_adr_i), + .wbm_stb_i(wbm_stb_i), + .wbm_dat_o(wbm_dat_o), + .wbm_ack_o(wbm_ack_o), + + // Slave Interface + .wbs_stb_o(wbs_stb_i), + .wbs_dat_i(wbs_dat_o), + .wbs_ack_i(wbs_ack_o) + ); + + // Instantiate five dummy slaves for testing + dummy_slave dummy_slaves [`NS-1:0]( + .wb_clk_i({`NS{wb_clk_i}}), + .wb_rst_i({`NS{wb_rst_i}}), + .wb_stb_i(wbs_stb_i), + .wb_cyc_i(wbm_cyc_i), + .wb_we_i(wbm_we_i), + .wb_sel_i(wbm_sel_i), + .wb_adr_i(wbm_adr_i), + .wb_dat_i(wbm_dat_i), + .wb_dat_o(wbs_dat_o), + .wb_ack_o(wbs_ack_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/la_wb/Makefile b/verilog/dv/wb_utests/wb_utests/la_wb/Makefile new file mode 100644 index 0000000..1b76d6b --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/la_wb/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = la_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd + +.PHONY: clean all
diff --git a/verilog/dv/wb_utests/wb_utests/la_wb/la_wb_tb.v b/verilog/dv/wb_utests/wb_utests/la_wb/la_wb_tb.v new file mode 100644 index 0000000..c1548c9 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/la_wb/la_wb_tb.v
@@ -0,0 +1,224 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none +`timescale 1 ns / 1 ps + +`include "la_wb.v" + +module la_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("la_wb_tb.vcd"); + $dumpvars(0, la_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Wishbone LA Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + // LA Wishbone Internal Register Addresses + wire [31:0] la_data_adr_0 = uut.BASE_ADR | uut.LA_DATA_0; + wire [31:0] la_data_adr_1 = uut.BASE_ADR | uut.LA_DATA_1; + wire [31:0] la_data_adr_2 = uut.BASE_ADR | uut.LA_DATA_2; + wire [31:0] la_data_adr_3 = uut.BASE_ADR | uut.LA_DATA_3; + + wire [31:0] la_ena_adr_0 = uut.BASE_ADR | uut.LA_ENA_0; + wire [31:0] la_ena_adr_1 = uut.BASE_ADR | uut.LA_ENA_1; + wire [31:0] la_ena_adr_2 = uut.BASE_ADR | uut.LA_ENA_2; + wire [31:0] la_ena_adr_3 = uut.BASE_ADR | uut.LA_ENA_3; + + reg [31:0] la_data_0; + reg [31:0] la_data_1; + reg [31:0] la_data_2; + reg [31:0] la_data_3; + + reg [31:0] la_ena_0; + reg [31:0] la_ena_1; + reg [31:0] la_ena_2; + reg [31:0] la_ena_3; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Write to la data registers + la_data_0 = $urandom_range(0, 2**32); + la_data_1 = $urandom_range(0, 2**32); + la_data_2 = $urandom_range(0, 2**32); + la_data_3 = $urandom_range(0, 2**32); + + write(la_data_adr_0, la_data_0); + write(la_data_adr_1, la_data_1); + write(la_data_adr_2, la_data_2); + write(la_data_adr_3, la_data_3); + + #2; + // Read from la data registers + read(la_data_adr_0); + if (wb_dat_o !== la_data_0) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_data_adr_1); + if (wb_dat_o !== la_data_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_data_adr_2); + if (wb_dat_o !== la_data_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_data_adr_3); + if (wb_dat_o !== la_data_3) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + // Write to la emable registers + la_ena_0 = $urandom_range(0, 2**32); + la_ena_1 = $urandom_range(0, 2**32); + la_ena_2 = $urandom_range(0, 2**32); + la_ena_3 = $urandom_range(0, 2**32); + + write(la_ena_adr_0, la_ena_0); + write(la_ena_adr_1, la_ena_1); + write(la_ena_adr_2, la_ena_2); + write(la_ena_adr_3, la_ena_3); + + #2; + // Read from la data registers + read(la_ena_adr_0); + if (wb_dat_o !== la_ena_0) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_ena_adr_1); + if (wb_dat_o !== la_ena_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_ena_adr_2); + if (wb_dat_o !== la_ena_1) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + + read(la_ena_adr_3); + if (wb_dat_o !== la_ena_3) begin + $display("Monitor: Error reading from la data_0 reg"); + $finish; + end + #6; + $display("Monitor: Test LA Wishbone Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + la_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/mem_wb/Makefile b/verilog/dv/wb_utests/wb_utests/mem_wb/Makefile new file mode 100644 index 0000000..4ed37bf --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/mem_wb/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = mem_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd + +.PHONY: clean all
diff --git a/verilog/dv/wb_utests/wb_utests/mem_wb/mem_wb_tb.v b/verilog/dv/wb_utests/wb_utests/mem_wb/mem_wb_tb.v new file mode 100644 index 0000000..549f904 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/mem_wb/mem_wb_tb.v
@@ -0,0 +1,159 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`define USE_OPENRAM + +`include "sram_1rw1r_32_8192_8_sky130.v" +`include "mem_wb.v" + +module mem_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + reg [3:0] wb_sel_i; + reg wb_we_i; + reg wb_cyc_i; + reg wb_stb_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + + wb_stb_i = 0; // master select-signal for the slave + wb_we_i = 0; // R = 0 , W = 1 + wb_cyc_i = 0; // master is transferring + wb_adr_i = 0; // input addr 32-bits + wb_dat_i = 0; // input data 32-bits + wb_sel_i = 0; // where data is available on data_i 4-bits + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("mem_wb_tb.vcd"); + $dumpvars(0, mem_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Wishbone Memory Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [31:0] ref_data [255: 0]; + reg [31: 0] read_data; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Randomly Write to memory array + for ( i = 0; i < 1; i = i + 1) begin + ref_data[i] = $urandom_range(0, 2**30); + write(i, ref_data[i]); + #2; + end + + #6; + for ( i = 0; i < 1; i = i + 1) begin + read(i); + if (wb_dat_o !== ref_data[i]) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", ref_data[i], wb_dat_o); + $display("Monitor: Wishbone Memory Failed"); + $display("%c[0m",27); + $finish; + end + #2; + end + #6; + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + mem_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_cyc_i(wb_cyc_i), + .wb_stb_i(wb_stb_i), + + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/mprj_ctrl/Makefile b/verilog/dv/wb_utests/wb_utests/mprj_ctrl/Makefile new file mode 100644 index 0000000..f354018 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/mprj_ctrl/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = mprj_ctrl + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/mprj_ctrl/mprj_ctrl_tb.v b/verilog/dv/wb_utests/wb_utests/mprj_ctrl/mprj_ctrl_tb.v new file mode 100644 index 0000000..5d86450 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/mprj_ctrl/mprj_ctrl_tb.v
@@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`include "mprj_ctrl.v" + +module mprj_ctrl_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + // Mega Project Control Registers + wire [31:0] mprj_ctrl = uut.BASE_ADR; + wire [31:0] pwr_ctrl = uut.BASE_ADR + uut.IO_PADS*4; + + initial begin + $dumpfile("mprj_ctrl_tb.vcd"); + $dumpvars(0, mprj_ctrl_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Mega-Project Control Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + reg [31:0] data; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + for (i=0; i<uut.IO_PADS; i=i+1) begin + data = $urandom_range(0, 2**(7)); + write(mprj_ctrl+i*4, data); + #2; + read(mprj_ctrl+i*4); + if (wb_dat_o !== data) begin + $display("Monitor: R/W from IO-CTRL Failed."); + $finish; + end + end + + for (i=0; i<uut.PWR_CTRL; i=i+1) begin + data = $urandom_range(0, 2**(7)); + write(pwr_ctrl+i*4, data); + #2; + read(pwr_ctrl+i*4); + if (wb_dat_o !== data) begin + $display("Monitor: R/W from POWER-CTRL Failed."); + $finish; + end + end + + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + mprj_ctrl_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/spi_sysctrl_wb/Makefile b/verilog/dv/wb_utests/wb_utests/spi_sysctrl_wb/Makefile new file mode 100644 index 0000000..8bf03c7 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/spi_sysctrl_wb/Makefile
@@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = spi_sysctrl_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all +
diff --git a/verilog/dv/wb_utests/wb_utests/spi_sysctrl_wb/spi_sysctrl_wb_tb.v b/verilog/dv/wb_utests/wb_utests/spi_sysctrl_wb/spi_sysctrl_wb_tb.v new file mode 100644 index 0000000..a5baf05 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/spi_sysctrl_wb/spi_sysctrl_wb_tb.v
@@ -0,0 +1,242 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`include "spi_sysctrl.v" +`include "striVe_spi.v" + +module spi_sysctrl_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + wire [7:0] spi_ro_config; // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + wire [4:0] spi_ro_pll_div; + wire [2:0] spi_ro_pll_sel; + wire spi_ro_xtal_ena; + wire spi_ro_reg_ena; + wire [25:0] spi_ro_pll_trim; + wire spi_ro_pll_dco_ena; + wire [11:0] spi_ro_mfgr_id; + wire [7:0] spi_ro_prod_id; + wire [3:0] spi_ro_mask_rev; + wire spi_ro_pll_bypass; + + // HKSPI + reg RSTB; + reg SCK; + reg SDI; + reg CSB; + reg trap; + reg [3:0] mask_rev_in; + + wire SDO; + wire sdo_enb; + wire xtal_ena; + wire reg_ena; + wire pll_dco_ena; + wire [25:0] pll_trim; + wire [2:0] pll_sel; + wire [4:0] pll_div; + wire pll_bypass; + wire irq; + wire reset; + wire RST; + wire [11:0] mfgr_id; + wire [7:0] prod_id; + wire [3:0] mask_rev; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + CSB = 1; + SCK = 0; + SDI = 0; + RSTB = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + // System Control Default Register Addresses (Read-only reg) + wire [31:0] spi_cfg = uut.BASE_ADR | uut.SPI_CFG; // unused & reserved ? + wire [31:0] spi_ena = uut.BASE_ADR | uut.SPI_ENA; + wire [31:0] spi_pll_cfg = uut.BASE_ADR | uut.SPI_PLL_CFG; + wire [31:0] spi_mfgr_id = uut.BASE_ADR | uut.SPI_MFGR_ID; + wire [31:0] spi_prod_id = uut.BASE_ADR | uut.SPI_PROD_ID; + wire [31:0] spi_mask_rev = uut.BASE_ADR | uut.SPI_MASK_REV; + wire [31:0] spi_pll_bypass = uut.BASE_ADR | uut.SPI_PLL_BYPASS; + + initial begin + $dumpfile("spi_sysctrl_wb_tb.vcd"); + $dumpvars(0, spi_sysctrl_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test SPI System Control Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + initial begin + // Reset Operation + wb_rst_i = 1; + RSTB = 0; // active low reset + #2; + wb_rst_i = 0; + RSTB = 1; + #2; + + // Read mask_rev register + mask_rev_in = 4'hF; + read(spi_mask_rev); + if (wb_dat_o !== {28'd0, mask_rev_in}) begin + $display("Error reading mask_rev reg"); + $finish; + end + + // Read manufacture id register + read(spi_mfgr_id); + if (wb_dat_o !== {20'd0, 12'h456}) begin + $display("Error reading manufacture id reg"); + $finish; + end + + // Read product id register + read(spi_prod_id); + if (wb_dat_o !== {24'd0, 8'h05}) begin + $display("Error reading product id reg"); + $finish; + end + + // Read PLL-Bypass register + read(spi_pll_bypass); + if (wb_dat_o !== {31'd0, 1'b1}) begin + $display("Error reading pll bypass id reg"); + $finish; + end + + // Read PLL-Configuration register + read(spi_pll_cfg); + if (wb_dat_o !== {5'd0, spi_ro_pll_trim, spi_ro_pll_dco_ena}) begin + $display("Error reading pll bypass id reg"); + $finish; + end + + // Read SPI Enables register + read(spi_ena); + if (wb_dat_o !== {22'd0, spi_ro_pll_div, spi_ro_pll_sel, spi_ro_xtal_ena, spi_ro_reg_ena}) begin + $display("Error reading pll bypass id reg"); + $finish; + end + $display("Success!"); + $finish; + end + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Monitor: Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Monitor: Read Cycle Ended."); + end + endtask + + spi_sysctrl_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + + .spi_ro_config(spi_ro_config), // (verify) wire input to the core not connected to HKSPI, what should it be connected to ? + .spi_ro_pll_div(spi_ro_pll_div), + .spi_ro_pll_sel(spi_ro_pll_sel), + .spi_ro_xtal_ena(spi_ro_xtal_ena), + .spi_ro_reg_ena(spi_ro_reg_ena), + + .spi_ro_pll_trim(spi_ro_pll_trim), + .spi_ro_pll_dco_ena(spi_ro_pll_dco_ena), + + .spi_ro_mfgr_id(spi_ro_mfgr_id), + .spi_ro_prod_id(spi_ro_prod_id), + .spi_ro_mask_rev(spi_ro_mask_rev), + .pll_bypass(spi_ro_pll_bypass) + ); + + striVe_spi hkspi ( + .RSTB(RSTB), + .SCK(SCK), + .SDI(SDI), + .CSB(CSB), + + .SDO(SDO), + .sdo_enb(SDO_enb), + .xtal_ena(spi_ro_xtal_ena), + .reg_ena(spi_ro_reg_ena), + .pll_dco_ena(spi_ro_pll_dco_ena), + .pll_sel(spi_ro_pll_sel), + .pll_div(spi_ro_pll_div), + .pll_trim(spi_ro_pll_trim), + .pll_bypass(spi_ro_pll_bypass), + .irq(irq_spi), + .RST(por), + .reset(ext_reset), + .trap(trap), + .mfgr_id(spi_ro_mfgr_id), + .prod_id(spi_ro_prod_id), + .mask_rev_in(mask_rev_in), + .mask_rev(spi_ro_mask_rev) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/spimemio_wb/Makefile b/verilog/dv/wb_utests/wb_utests/spimemio_wb/Makefile new file mode 100644 index 0000000..d145f04 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/spimemio_wb/Makefile
@@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = spimemio_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../ -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all +
diff --git a/verilog/dv/wb_utests/wb_utests/spimemio_wb/flash.hex b/verilog/dv/wb_utests/wb_utests/spimemio_wb/flash.hex new file mode 100644 index 0000000..23bd76d --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/spimemio_wb/flash.hex
@@ -0,0 +1,6 @@ +@10000000 +a1 +b1 +c1 +d1 +f1 \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/spimemio_wb/spimemio_wb_tb.v b/verilog/dv/wb_utests/wb_utests/spimemio_wb/spimemio_wb_tb.v new file mode 100644 index 0000000..febc124 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/spimemio_wb/spimemio_wb_tb.v
@@ -0,0 +1,233 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`define FLASH_BASE 32'h 1000_000 + +`include "spimemio.v" +// `include "spiflash.v" + +module spimemio_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_flash_stb_i; + reg wb_cfg_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + + wire wb_flash_ack_o; + wire wb_cfg_ack_o; + wire [31:0] wb_flash_dat_o; + wire [31:0] wb_cfg_dat_o; + + wire flash_csb; + wire flash_clk; + + wire flash_io0_oeb; + wire flash_io1_oeb; + wire flash_io2_oeb; + wire flash_io3_oeb; + + wire flash_io0_di = 1'b 1; + wire flash_io1_di = 1'b 1; + wire flash_io2_di = 1'b 1; + wire flash_io3_di = 1'b 1; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_flash_stb_i = 0; + wb_cfg_stb_i = 0; + wb_cyc_i = 0; + wb_we_i = 0; + wb_sel_i = 0; + wb_adr_i = 0; + wb_dat_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + spimemio_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_flash_stb_i(wb_flash_stb_i), + .wb_cfg_stb_i(wb_cfg_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_we_i(wb_we_i), + .wb_sel_i(wb_sel_i), + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_flash_ack_o(wb_flash_ack_o), + .wb_cfg_ack_o(wb_cfg_ack_o), + .wb_flash_dat_o(wb_flash_dat_o), + .wb_cfg_dat_o(wb_cfg_dat_o), + + .flash_clk(flash_clk), + .flash_csb(flash_csb), + + .flash_io0_oeb(flash_io0_oeb), + .flash_io1_oeb(flash_io1_oeb), + .flash_io2_oeb(flash_io2_oeb), + .flash_io3_oeb(flash_io3_oeb), + + .flash_io0_di(flash_io0_di), + .flash_io1_di(flash_io1_di), + .flash_io2_di(flash_io2_di), + .flash_io3_di(flash_io3_di) + ); + + initial begin + $dumpfile("spimemio_wb_tb.vcd"); + $dumpvars(0, spimemio_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test spimmemio Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + wire [31:0] cfgreg_data; + assign cfgreg_data = { + 1'b 1, + 8'b 0, + 3'b 111, + 4'b 1010, + 4'b 0, // make sure is it tied to zero in the module itself + {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb}, + 2'b 0, + flash_csb, + flash_clk, + {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di} + }; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Read from flash + for (i = `FLASH_BASE; i < `FLASH_BASE + 100 ; i = i + 4) begin + read(i, 1, 0); + if (wb_flash_dat_o !== 32'hFFFF_FFFF) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", 32'hFFFF_FFFF, wb_flash_dat_o); + $display("Monitor: Wishbone spimemio Failed"); + $display("%c[0m",27); + $finish; + end + #2; + end + + #6; + // Write to Configuration register + write(cfgreg_data, 0); + #2; + read(0, 0, 1); + if (wb_cfg_dat_o !== cfgreg_data) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", cfgreg_data, wb_cfg_dat_o); + $display("Monitor: Wishbone spimemio Failed"); + $display("%c[0m",27); + $finish; + end + + $display("Success!"); + $finish; + end + + task write; + input [32:0] data; + input [31:0] addr; + begin + @(posedge wb_clk_i) begin + wb_cfg_stb_i = 1'b 1; + wb_flash_stb_i = 1'b 0; + wb_cyc_i = 1'b 1; + wb_sel_i = 4'b 1111; // complete word + wb_we_i = 1'b 1; // write enable + wb_adr_i = addr; + wb_dat_i = data; + end + + wait_ack(); + end + endtask + + task read; + input [32:0] addr; + input flash_stb; + input cfg_stb; + begin + wb_flash_stb_i = flash_stb; + wb_cfg_stb_i = cfg_stb; + + wb_cyc_i = 1'b 1; + wb_adr_i = addr; + wb_dat_i = 24; + wb_sel_i = 4'b 1111; // complete word + wb_we_i = 1'b 0; // read + $display("Initiated Read transaction..."); + wait_ack(); + end + endtask + + task wait_ack; + // Wait for an ACK + if (wb_cfg_stb_i == 1) begin + @(posedge wb_cfg_ack_o) begin + #2; // To end the transaction on the falling edge of ack + wb_cyc_i = 1'b 0; + wb_cfg_stb_i = 1'b 0; + $display("Monitor: Received an ACK from slave"); + end + end + else begin + @(posedge wb_flash_ack_o) begin + #2; // To end the transaction on the falling edge of ack + wb_cyc_i = 1'b 0; + wb_flash_stb_i = 1'b 0; + $display("Monitor: Received an ACK from slave"); + end + end + endtask + + // spiflash #( + // .FILENAME("flash.hex") + // ) spiflash ( + // .csb(flash_csb), + // .clk(flash_clk), + // .io0(flash_io0), + // .io1(flash_io1), + // .io2(flash_io2), + // .io3(flash_io3) + // ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/storage_wb/Makefile b/verilog/dv/wb_utests/wb_utests/storage_wb/Makefile new file mode 100644 index 0000000..d080bcf --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/storage_wb/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = storage_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/storage_wb/storage_wb_tb.v b/verilog/dv/wb_utests/wb_utests/storage_wb/storage_wb_tb.v new file mode 100644 index 0000000..0cc6b78 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/storage_wb/storage_wb_tb.v
@@ -0,0 +1,228 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none +// `define DBG + +`define STORAGE_BASE_ADR 32'h0100_0000 + +`include "defines.v" +`include "sram_1rw1r_32_256_8_sky130.v" +`include "storage.v" +`include "storage_bridge_wb.v" + +module storage_tb; + + localparam [(`RAM_BLOCKS*24)-1:0] STORAGE_RW_ADR = { + {24'h 10_0000}, + {24'h 00_0000} + }; + + localparam [23:0] STORAGE_RO_ADR = { + {24'h 20_0000} + }; + + reg wb_clk_i; + reg wb_rst_i; + + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + reg [3:0] wb_sel_i; + reg wb_we_i; + reg wb_cyc_i; + reg [1:0] wb_stb_i; + wire [1:0] wb_ack_o; + wire [31:0] wb_rw_dat_o; + + // MGMT_AREA RO WB Interface + wire [31:0] wb_ro_dat_o; + + wire [`RAM_BLOCKS-1:0] mgmt_ena; + wire [(`RAM_BLOCKS*4)-1:0] mgmt_wen_mask; + wire [`RAM_BLOCKS-1:0] mgmt_wen; + wire [31:0] mgmt_wdata; + wire [7:0] mgmt_addr; + wire [(`RAM_BLOCKS*32)-1:0] mgmt_rdata; + wire ro_ena; + wire [7:0] ro_addr; + wire [31:0] ro_rdata; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("storage.vcd"); + $dumpvars(0, storage_tb); + repeat (100) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test Storage Area Failed"); + $display("%c[0m",27); + $finish; + end + + reg [31:0] ref_data [255: 0]; + reg [(24*`RAM_BLOCKS)-1:0] storage_rw_adr = STORAGE_RW_ADR; + reg [23:0] storage_ro_adr = STORAGE_RO_ADR; + reg [31:0] block_adr; + + integer i,j; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Test MGMT R/W port and user RO port + for (i = 0; i<`RAM_BLOCKS; i = i +1) begin + for ( j = 0; j < 100; j = j + 1) begin + if (i == 0) begin + ref_data[j] = $urandom_range(0, 2**30); + end + block_adr = (storage_rw_adr[24*i+:24] + (j << 2)) | `STORAGE_BASE_ADR; + write(block_adr, ref_data[j]); + #2; + end + end + + for (i = 0; i<`RAM_BLOCKS; i = i +1) begin + for ( j = 0; j < 100; j = j + 1) begin + block_adr = (storage_rw_adr[24*i+:24] + (j << 2)) | `STORAGE_BASE_ADR; + read(block_adr, 0); + if (wb_rw_dat_o !== ref_data[j]) begin + $display("Got %0h, Expected %0h from addr %0h: ",wb_rw_dat_o,ref_data[j], block_adr); + $display("Monitor: MGMT R/W Operation Failed"); + $finish; + end + + if (i == 0) begin + block_adr = (storage_ro_adr + (j << 2)) | `STORAGE_BASE_ADR; + read(block_adr, 1); + if (wb_ro_dat_o !== ref_data[j]) begin + $display("Monitor: MGMT RO Operation Failed"); + $finish; + end + end + #2; + end + end + + $display("Success"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i[0] = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o[0] == 1); + wait(wb_ack_o[0] == 0); + wb_cyc_i = 0; + wb_stb_i[0] = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + input integer interface; + begin + @(posedge wb_clk_i) begin + wb_stb_i[interface] = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o[interface] == 1); + wait(wb_ack_o[interface] == 0); + wb_cyc_i = 0; + wb_stb_i[interface] = 0; + $display("Read Cycle Ended."); + end + endtask + + storage_bridge_wb #( + .RW_BLOCKS_ADR(STORAGE_RW_ADR), + .RO_BLOCKS_ADR(STORAGE_RO_ADR) + ) wb_bridge ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_cyc_i(wb_cyc_i), + .wb_stb_i(wb_stb_i), + .wb_ack_o(wb_ack_o), + .wb_rw_dat_o(wb_rw_dat_o), + + // MGMT_AREA RO WB Interface + .wb_ro_dat_o(wb_ro_dat_o), + + // MGMT Area native memory interface + .mgmt_ena(mgmt_ena), + .mgmt_wen_mask(mgmt_wen_mask), + .mgmt_wen(mgmt_wen), + .mgmt_addr(mgmt_addr), + .mgmt_wdata(mgmt_wdata), + .mgmt_rdata(mgmt_rdata), + // MGMT_AREA RO Interface + .mgmt_ena_ro(ro_ena), + .mgmt_addr_ro(ro_addr), + .mgmt_rdata_ro(ro_rdata) + ); + + storage uut ( + // Management R/W WB interface + .mgmt_clk(wb_clk_i), + .mgmt_ena(mgmt_ena), + .mgmt_wen(mgmt_wen), + .mgmt_wen_mask(mgmt_wen_mask), + .mgmt_addr(mgmt_addr), + .mgmt_wdata(mgmt_wdata), + .mgmt_rdata(mgmt_rdata), + // Management RO interface + .mgmt_ena_ro(ro_ena), + .mgmt_addr_ro(ro_addr), + .mgmt_rdata_ro(ro_rdata) + ); + +endmodule \ No newline at end of file
diff --git a/verilog/dv/wb_utests/wb_utests/sysctrl_wb/Makefile b/verilog/dv/wb_utests/wb_utests/sysctrl_wb/Makefile new file mode 100644 index 0000000..89aa77b --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/sysctrl_wb/Makefile
@@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = sysctrl_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all +
diff --git a/verilog/dv/wb_utests/wb_utests/sysctrl_wb/sysctrl_wb_tb.v b/verilog/dv/wb_utests/wb_utests/sysctrl_wb/sysctrl_wb_tb.v new file mode 100644 index 0000000..cf80e03 --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/sysctrl_wb/sysctrl_wb_tb.v
@@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "sysctrl.v" + +module sysctrl_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_dat_i; + reg [31:0] wb_adr_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_cyc_i = 0; + wb_sel_i = 0; + wb_we_i = 0; + wb_dat_i = 0; + wb_adr_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("sysctrl_wb_tb.vcd"); + $dumpvars(0, sysctrl_wb_tb); + repeat (50) begin + repeat (1000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display ("Monitor: Timeout, Test System Control Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + // System Control Default Register Addresses + wire [31:0] clk1_out_adr = uut.BASE_ADR | uut.CLK1_OUT; + wire [31:0] clk2_out_adr = uut.BASE_ADR | uut.CLK2_OUT; + wire [31:0] trap_out_adr = uut.BASE_ADR | uut.TRAP_OUT; + wire [31:0] irq7_src_adr = uut.BASE_ADR | uut.IRQ7_SRC; + wire [31:0] irq8_src_adr = uut.BASE_ADR | uut.IRQ8_SRC; + + reg clk1_output_dest; + reg clk2_output_dest; + reg trap_output_dest; + reg irq_7_inputsrc; + reg irq_8_inputsrc; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + clk1_output_dest = 1'b1; + clk2_output_dest = 1'b1; + trap_output_dest = 1'b1; + irq_7_inputsrc = 1'b1; + irq_8_inputsrc = 1'b1; + + // Write to System Control Registers + write(clk1_out_adr, clk1_output_dest); + write(clk2_out_adr, clk2_output_dest); + write(trap_out_adr, trap_output_dest); + write(irq7_src_adr, irq_7_inputsrc); + write(irq8_src_adr, irq_8_inputsrc); + #2; + read(clk1_out_adr); + if (wb_dat_o !== clk1_output_dest) begin + $display("Error reading CLK1 output destination register."); + $finish; + end + + read(clk2_out_adr); + if (wb_dat_o !== clk2_output_dest) begin + $display("Error reading CLK2 output destination register."); + $finish; + end + + read(trap_out_adr); + if (wb_dat_o !== trap_output_dest) begin + $display("Error reading trap output destination register."); + $finish; + end + + read(irq7_src_adr); + if (wb_dat_o !== irq_7_inputsrc) begin + $display("Error reading IRQ7 input source register."); + $finish; + end + + read(irq8_src_adr); + if (wb_dat_o !== irq_8_inputsrc) begin + $display("Error reading IRQ8 input source register."); + $finish; + end + + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Monitor: Write Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Monitor: Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Monitor: Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Monitor: Read Cycle Ended."); + end + endtask + + sysctrl_wb uut( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_dat_i(wb_dat_i), + .wb_adr_i(wb_adr_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o) + ); + +endmodule
diff --git a/verilog/dv/wb_utests/wb_utests/uart_wb/Makefile b/verilog/dv/wb_utests/wb_utests/uart_wb/Makefile new file mode 100644 index 0000000..d1c587f --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/uart_wb/Makefile
@@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +.SUFFIXES: + +PATTERN = uart_wb + +all: ${PATTERN:=.vcd} + +%.vvp: %_tb.v + iverilog -I .. -I ../../ -I ../../../rtl \ + $< -o $@ + +%.vcd: %.vvp + vvp $< + +clean: + rm -f *.vvp *.vcd *.log + +.PHONY: clean all
diff --git a/verilog/dv/wb_utests/wb_utests/uart_wb/uart_wb_tb.v b/verilog/dv/wb_utests/wb_utests/uart_wb/uart_wb_tb.v new file mode 100644 index 0000000..0bbefdf --- /dev/null +++ b/verilog/dv/wb_utests/wb_utests/uart_wb/uart_wb_tb.v
@@ -0,0 +1,168 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +`default_nettype none + + +`timescale 1 ns / 1 ps + +`include "simpleuart.v" + +module uart_wb_tb; + + reg wb_clk_i; + reg wb_rst_i; + + reg wb_stb_i; + reg wb_cyc_i; + reg wb_we_i; + reg [3:0] wb_sel_i; + reg [31:0] wb_adr_i; + reg [31:0] wb_dat_i; + + wire wb_ack_o; + wire [31:0] wb_dat_o; + + wire tbuart_rx; + wire ser_rx; + + initial begin + wb_clk_i = 0; + wb_rst_i = 0; + wb_stb_i = 0; + wb_we_i = 0; + wb_cyc_i = 0; + wb_adr_i = 0; + wb_dat_i = 0; + wb_sel_i = 0; + end + + always #1 wb_clk_i = ~wb_clk_i; + + initial begin + $dumpfile("uart_wb_tb.vcd"); + $dumpvars(0, uart_wb_tb); + repeat (500) begin + repeat (10000) @(posedge wb_clk_i); + end + $display("%c[1;31m",27); + $display("Monitor: Timeout, Test UART Failed"); + $display("%c[0m",27); + $finish; + end + + integer i; + + wire [31:0] div_reg_addr = uut.BASE_ADR | uut.CLK_DIV; + wire [31:0] div_reg_data = 32'h FFFF_FFFF; + + wire [31:0] dat_reg_addr = uut.BASE_ADR | uut.DATA; + wire [31:0] dat_reg_data = 32'h FFFF_FFFF; + + initial begin + // Reset Operation + wb_rst_i = 1; + #2; + wb_rst_i = 0; + #2; + + // Write to div register + write(div_reg_addr, div_reg_data); + #2; + read(div_reg_addr); + if (wb_dat_o !== div_reg_data) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", div_reg_data, wb_dat_o); + $display("Monitor: Wishbone UART Failed"); + $display("%c[0m",27); + $finish; + end + #6; + + // Write Operation: writes to data register + write(dat_reg_addr, dat_reg_data); + #2; + read(dat_reg_addr); + if (wb_dat_o !== dat_reg_data) begin + $display("%c[1;31m",27); + $display("Expected %0b, but Got %0b ", dat_reg_data, wb_dat_o); + $display("Monitor: Wishbone UART Failed"); + $display("%c[0m",27); + $finish; + end + $display("Success!"); + $finish; + end + + task write; + input [32:0] addr; + input [32:0] data; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_sel_i = 4'hF; + wb_we_i = 1; + wb_adr_i = addr; + wb_dat_i = data; + $display("Write Cycle Started."); + end + #2; + wb_we_i = 0; + // Wait for an ACK + wait(wb_ack_o == 1); + #2; + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Write Cycle Ended."); + end + endtask + + task read; + input [32:0] addr; + begin + @(posedge wb_clk_i) begin + wb_stb_i = 1; + wb_cyc_i = 1; + wb_we_i = 0; + wb_adr_i = addr; + $display("Read Cycle Started."); + end + // Wait for an ACK + wait(wb_ack_o == 1); + #2; + // wait(wb_ack_o == 0); + wb_cyc_i = 0; + wb_stb_i = 0; + $display("Read Cycle Ended."); + end + endtask + + simpleuart_wb uut ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + .wb_stb_i(wb_stb_i), + .wb_cyc_i(wb_cyc_i), + .wb_sel_i(wb_sel_i), + .wb_we_i(wb_we_i), + .wb_adr_i(wb_adr_i), + .wb_dat_i(wb_dat_i), + .wb_ack_o(wb_ack_o), + .wb_dat_o(wb_dat_o), + .ser_tx(tbuart_rx), + .ser_rx(ser_rx) + ); + +endmodule