< HCAB Home

HCAB - Hierarchic Cabbage

I somehow got stuck on some ECRC project promoting cooperation between companies and as my part did some work on porting a chip design package (HCAB), characterizing chips, writting output routines for a huge Versatec plotter and to a tape for manufacture, and yakking away on a committee trying to get some standardizaton between a collection of different cell design databases.

Somewhere along the line I wrote an interpreter for a chip characterization program which automatically ran SPICE with different values stuck in and interpreted the results. An enormous amount of time was being wasted by people doing this by hand - it could take a week for a single chip and I hoped to reduce this to half an hour. My interpreter didn't get far as I was moved before it all worked well, and maybe it was a bit over-clever. Anyway everyone should try their hand at designing a new language sometime ;-)

The language was designed to be SPICE friendly in its syntax and to be able to use FORTRAN subroutines - I think I was being influenced by ADA at the time as well. The data and program was all held in dynamically allocated arrays which formed a tree structure but could never form a cycle so freeing could be done easily and automatically. References were in fact 'locators' - an array of integers saying the stack level, then the field or index number going down the structures. There was no sharing of substructures except if they were constant.

Anyway here is an example I've dredged up:

//  defaults
const volt'  vdd_volts = 5v
const float' tempdc = 110
const float' vdd_resistance = 1ohm
const float' vss_resistance = 1ohm
const time'  time_step = 1nsec
const time'  max_setup_time = 2onsec
const time'  max_hold_time = 20nsec
const time'  max _response_time = 20nsec
const volt'  logic_1_input = O.99*vdd_volts
const volt'  logic_0_input = 0.02*vdd_volts
const volt'  logic_1_low = 0.80*vdd_volts
const volt'  logic_0_high = 0.20*vdd_volts
const time'  rising_edge = 2nsec
const time'  falling_edge = 2nsec
const float' output_nodal_capacitance = 0.lpf
const volt'  rise_time_mark_low = 0.10*vdd_volts
const volt'  rise_time_mark_high = O.90*vdd_volts
const float' acceptable_transition_degradation_factor = 2
const volt'  measurement_level = 0.50*vdd_volts

//  sweep default if GO is used
sweep time from 0 to max_response_time by time_step


//  define vdd and vis pins
//  set up cell_vdd and cell_vss
//  put in source voltage resistances
//  put in power voltage
macro power(pin'vdd. pin'vss)
local pin'vddx=newpin(), pin'vssx=newpin()
var pin'cell_vdd=vdd
var pin'cell_vss=vss
gen "RVDD" vdd vddx vdd_resistance
gen "RVSS" vss vssx vss_resistance
gen "VSSX" vssx vddx vdd_volts
endmacro

//  define input pins
//  put into list cell_inputs
macro inputs list'pins
var list'cell_inputs = pins
endmacro

//  define output pins
//  put into list cell_outputs
//  add a capacitance to each output
macro outputs list'pins
var list'cell_outputs = pins
local int'i=1
label loop
  if i>bound'pins
    return
  endif
  gen concat("COUT",pins[i]) pins[1] cell_vdd output_nodal_capacitance
  i=i+1
  goto loop
endmacro

//  define unused pins
//  put into list cell_unused
//  put in resistance to vdd
macro unused list'pins
var list'cell_unused = pins
local int'i=1
label loop
  if i>bound'pins
    return
  endif
  gen concat("RX",pins[i]) pins[i] cell_vdd 1OOOohms
  i=i+1
  goto loop
endmacro

//  generate a pulse for hold time measurement
//  will not reach v2 if width is negative, just get a spike
macro pwl'rise_fall(volt'v1 volt'v2 +
 time'delay=O +
 time'rise=rising_edge +
 tlme'fall=falling_edge +
 time'width=0)
if width >= 0
  return pwl(O v1 delay v1 delay+rise v2 delay+rise+width v2 +
             delay+rise+width+fall v1)
elsf rise+width <= 0
  return v1
else
  local float'x=(rise+width)/rise
  return pwl(0 v1 delay v1 delay+rise+width x*(v2-vl)+vl +
             delay+rise+width+x*fall v1)
endif
endmacro

//  A first stab at calculating hold time
macro hold(pin'in pwl'init pin'out +
 time'from time'to time'by ref'hold_time)
local time'low time'high time'mid
low=from
high=to
label loop
  mid=(low+high)/2
  TEST
    gen "vhold" in cell_vss pwl(O init +
from rise_fall(0 vdd_volts width=mid-from))
    sweep time from 0 to to by by
    keep v(out)
    GO
    if find(v(out)>=4.7)
      high = mid
    else
      low=mid
    endif
  ENDTEST
  if high-low > by
    goto loop
  endif
*hold_time = mid-from
endmacro