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