Programming 언어/Skill

[SKILL 강좌] calculate_area : 4. boolean button 과 export gds

호드맨 2017. 1. 12. 15:04

gui 설정을 다 했다고 생각했는데 한 가지만 더 추가해보자. (역시 옵션은 하다 보면 자꾸 늘어남) 해당 layout DB의 gds를 뽑아서 calibre (SVRF)로 면적을 확인하려고 하는데, gds를 뽑을 건지 정해진 path에 기존에 뽑혀 있는 gds를 사용할 건지 옵션을 추가해보자.

이 경우 t / nil로 동작하는 boolean button 이 필요하게 된다. 앞 단계에서 만든 것과 유사하지만 다른 type인 boolean button을 만들어 보고 calculate_area() 함수에 export_gds 함수를 만들어 연결하겠다. 조금은 더 복잡하겠지만 gds를 뽑는 동안 다음 단계로 넘어가면 안 되므로 background에서 실행하면서 streamOut 이 완료되는 시점을 기다리도록 해보겠다. 지금까지 만든 창에 Label을 만들어 놨었는데 그 Label의 Text를 수정하면서 상태를 알 수 있도록 하겠다.

이번에는 추가되는 코드는 짧지만 설명이 많이 필요할 듯하다.

;# 지난번에 만든 cal_run_button 다음에 아래를 추가해봅시다.

cal_gdsex_BB = hiCreateBooleanButton(
         ?name 'cal_gdsex_BB
         ?buttonText "Run with gds export"
         ?defVaule t
) ;end of cal_gdsex_BB

;# 역시나 calculatorID 쪽도 좀 고쳐봅시다. 하는 김에 Label 위치도 좀 바꿔봤습니다.

calculatorID = hiCreateAppForm(
         ?name 'calculator
         ?buttonLayout 'Empty
         ?formTitle "Layer Area Calculator"
         ?field
            list(
               list(cal_cellName_SF       040:020 280:030 70)
               list(cal_cur_button        315:020 100:040)
               list(cal_net_file_SF       040:060 380:030 70)
               list(cal_net_file_button   415:060 040:040)
               list(cal_top_layer_CF      060:100 040:040 120)
               list(cal_bot_layer_CF      060:130 040:040 120)
               list(cal_run_button        265:100 150:60)
               list(cal_gdsex_BB          060:160 150:060)
               list(cal_Label             265:170 180:030 14)
            );end of list
         ?initialSize list(500 250)
         ?minSize list(500 250)
) ;end of calculatorID

기존과 크게 다른 내용은 없이 추가한 것이 잘 보입니다. 이제 calculate_area 함수에서 gdsex 가 t 일 때와 nil 일 때, 각각 동작을 정해주고 그 후에 calculate_area_step 2 함수를 만들어 넘어가도록 하겠습니다. step 2는 gds가 생성될 동안 기다렸다가 준비되면 상태창으로 쓸 Label에 Stream Out Finish!! 를 보여주도록 합시다. 뽑는 동안은 기다리니 Streaming out.. text를 깜빡거리게 해 볼까요?


;# cal_export_gds 함수와 calculate_area_step2

;# 일단 cal_export_gds 함수를 만들어 봅시다. 사실 export_gds 함수를 따로 만들어
;# 범용으로 사용할 수도 있으나 여기는 calculator 만드는 중이라서 따로 이름을 주었습니다.

procedure(cal_export_gds()
   prog(()
      cv = deGetCellView()
      ipcProcess = ipcBeginProcess(sprintf(_tmp, "rm -f ../veri/4_gds/touch_streamOut ; strrmout -library \"%s\" -strmFile ../veri/4_gds/%s.gds -topCell \"%s\" -view \"%s\" -enableColoring > ../veri/4_gds/pipo.log ; touch ../veri/4_gds/touch_streamOut", cv->libName, cv-cellName, cv->cellName, cv->viewName)) -- (1)
   );end of prog
); end of procedure cal_export_gds

;# 주석
;# (1) : line 이 길어졌지만 해당 path 의 touch 파일을 지운 뒤, strmout 명령을 실행하고
;# 끝나면 touch 파일을 생성하도록 해 놓았다. ipcProcess 를 통해 실행하고 있고 블로그의
;# 예전 export gds 함수를 보면 여기서 ipcWait 을 사용하였는데 DB가 클경우 상당히 오래
;# virtuoso 가 멈추게 된다. 앞으로 설명할 스크립트로 이 ipc 명령어가 끝나길 기다려보자.

;# 이제 calculate_area 함수를 수정하고 calculate_area_step2 함수를 새로이 만들어 보겠다.

procedure(calculate_area()
   prog(()
      printf("CellName : %s\n" calculator->cal_cellName_SF->value)
      printf("We will reference %s, for Net information.\n" calculator->cal_net_file_SF->value)
      printf("Calculate Layer from %s to %s\n" calculator->cal_bot_layer_CF->value calculator->cal_top_layer_CF->value)
      if(calculator->cal_gdsex_BB->value == t then
          cal_export_gds()
      else
          ipcProcess = ipcBeginProcess("touch ../veri/4_gds/touch_streamOut") ; -- (2)
      );end of if
      
      hiRegTimer("calculate_area_step2()" 30) -- (3)
   );end of prog
);end of procedure calculate_area()

;# 위와 같이 수정하고, 아래 calculate_area_step2 는 새로이 추가하자.

procedure(calculate_area_step2()
   prog(()
      when(isFile("../veri/4_gds/touch_streamOut") ; -- (4)
         calculator->cal_Label->value = "Stream Out Finish!!"
         calculator->cal_Label->invisible = nil
         return(t)
      ) ;end of when
      if(calculator->cal_Label->invisible == t then
         calculator->cal_Label->invisible = nil
         calculator->cal_Label->value = "Streaming Out..."
      else
         calculator->cal_Label->invisible = t
      ) ; end of if
      hiRegTimer("calculate_area_step2()" 30) ; -- (5)
      return(t)
   );end of prog
);end of procedure

;# 주석

;# (2) : gdsex_BB 이 t 일 경우 위에서 만든 cal_export_gds 를 실행하며, nil 일 경우
;# step2 가 잘 진행 될 수 있도록 touch_streamOut 파일만 생성해주자.
;# (3) : 적당한 시간 후에 step2 를 시작할 것이다. DB의 크기에 따라 step2를 조절할
;# 필요는 없다. touch 구문이 실행되기 전까지 step2에서 기다릴 것이므로..
;# (4) : when isFile 함수로 해당 touch 파일 유무를 확인한다. 해당 파일이 없을 경우
;# when 안의 함수가 실행되지 읺고, touch 이후에만 실행되어 return(t) 구문에 의해
;# step2 의 루프가 끝날것이다. 이후에 추가될 함수들은 이 when 안의 return 이전에 넣어주면 된다.
;# (5) : 아직 touch 가 실행되기 전에는 if 구문에 의해 cal_Label 의 invisible 을 
;# 껐다 켰다 하면서 깜빡이는 효과를 주었으며 다시 자기자신을 hiRegTimer 에 의해 3초 후 
;# 실행하면서 streamOut 이 완료되기를 기다린다.

reload 한 뒤 TEST 용 DB에서 동작확인 한번 해보고 나서 덩치가 큰 DB에서도 테스트해보자. stream out 이 진행되는 동안 Label 이 3초 간격으로 깜빡거리다가 완료되고 나면 Streamout Finish!! 가 뜰 것이다. 1단계에서 streamout 후 2단계에서 1단계 완료를 기다리는 것까지는 완성했다.

이제 다음 단계에서는 2단계인 calibre 실행을 위해 runset 혹은 rule 파일을 생성하고 calibre 실행을 하도록 하자.

 

;# calculator.il 파일 전문

cal_cellName_SF = hiCreateStringField(
        ?name 'cal_cellName_SF
        ?prompt "Cell Name"
        ?defValue ""
        ?callback ""
) ;end of cal_cellName_SF

cal_cur_button = hiCreateButton(
        ?name 'cal_cur_button
        ?buttonText "Current Cell"
        ?callback "cal_cur_button_CB()"
) ;end of cal_cur_button

procedure(cal_cur_button_CB()
   prog(()
      calculator->cal_cellName_SF->value = deGetCellView()->cellName
   );end of prog
);end of procedure cal_cur_button_CB()

cal_net_file_SF = hiCreateStringField(
        ?name 'cal_net_file_SF
        ?prompt "Net File "
        ?defValue ""
        ?callback ""
) ;end of cal_net_file_SF

cal_net_file_button = hiCreateButton(
        ?name 'cal_net_file_button
        ?buttonText "..."
        ?callback "ddsFileBrowseCB(calculator 'cal_net_file_SF)"
) ;end cal_net_file_button

cal_top_layer_CF = hiCreateCyclicField(
        ?name 'cal_top_layer_CF
        ?choices list("m0" "m1" "m2" "m3" "m4" "m5" "m6" "m7" "m8" "m9" "m10" "m11" "TM0" "TM1")
        ?prompt "CHECK TOP LAYER"
        ?value "m11"
) ;end of cal_top_layer_CF

cal_bot_layer_CF = hiCreateCyclicField(
        ?name 'cal_bot_layer_CF
        ?choices list("m0" "m1" "m2" "m3" "m4" "m5" "m6" "m7" "m8" "m9" "m10" "m11" "TM0" "TM1")
        ?prompt "CHECK BOT LAYER"
        ?value "m1"
) ;end of cal_bot_layer_CF

cal_run_button = hiCreateButton(
        ?name 'cal_run_button
        ?buttonText "Calculate Area"
        ?callback "calculate_area()"
) ;end of cal_cur_button

cal_gdsex_BB = hiCreateBooleanButton(
        ?name 'cal_gdsex_BB
        ?buttonText "Run with gds export"
        ?defValue t
) ;end of cal_gdsex_BB

cal_Label = hiCreateLabel(
        ?name 'cal_Label
        ?labelText "skill programming!\nhttp://hodman.tistory.com"
) ;end of cal_Label

calculatorID = hiCreateAppForm(
          ?name 'calculator
          ?buttonLayout 'Empty
          ?formTitle "Layer Area Calculator"
          ?fields 
             list(
                list(cal_cellName_SF        040:020 280:030 70)
                list(cal_cur_button         315:020 100:040)
                list(cal_net_file_SF        040:060 380:030 70)
                list(cal_net_file_button    415:060 040:040)
                list(cal_top_layer_CF       060:100 040:040 120)
                list(cal_bot_layer_CF       060:130 040:040 120)
                list(cal_run_button         265:100 150:060)
                list(cal_gdsex_BB           060:160 150:060)
                list(cal_Label              265:170 180:030 14)
             );end of list

          ?initialSize list(500 250)
          ?minSize list(500 250)
);end of calculatorID

procedure(calculator()
   prog(()
      hiDisplayForm(calculator '(100 100))
   );end of prog
);end of procedure calculator()

procedure(reload()
   prog(()
      if(hiIsFormDisplayed(calculatorID) then
         hiFormCancel(calculator)
      ); end of if
      hiRegTimer("load(\"/user/hodman/private/skill/calculator.il\")" 1)
      hiRegTimer("calculator()" 10)
   );end of prog
);end of procedure reload()

procedure(calculate_area()
   prog(()
      printf("CellName : %s\n" calculator->cal_cellName_SF->value)
      printf("We will reference %s, for Net information.\n" calculator->cal_net_file_SF->value)
      printf("Calculate Layer from %s to %s\n" calculator->cal_bot_layer_CF->value calculator->cal_top_layer_CF->value)
      if(calculator->cal_gdsex_BB->value == t then
         cal_export_gds()
      else
         ipcProcess = ipcBeginProcess("touch ../veri/4_gds/touch_streamOut")
      );end of if
      hiRegTimer("calculate_area_step2()" 30)
   );end of prog
);end of procedure calculate_area()

procedure(calculate_area_step2()
   prog(()
      when(isFile("../veri/4_gds/touch_streamOut")
         calculator->cal_Label->value = "Stream Out Finish!!"
         calculator->cal_Label->invisble = nil
         return(t)
      )
      if(calculator->cal_Label->invisible == t then
         calculator->cal_Label->invisible = nil
         calculator->cal_Label->value = "Streaming Out.."
      else
         calculator->cal_Label->invisible = t
      );end of if
      hiRegTimer("calculate_area_step2()" 30)
      return(t)
   );end of prog
);end of procedure calculate_area_step2()
      
procedure(cal_export_gds()
   prog(()
      cv = hiGetCurrentWindow()->cellView
      ipcProcess = ipcBeginProcess(sprintf(_tmp, "rm -f ../veri/4_gds/touch_streamOut ; strmout -library \"%s\" -strmFile ../veri/4_gds/%s.gds -topCell \"%s\" -view \"%s\" -enableColoring > ../veri/4_gds/pipo.log ; touch ../veri/4_gds/touch_streamOut" , cv->libName, cv->cellName, cv->cellName, cv->viewName))
); end prog
); end procedure