### convenient object access ### sub ALF_Object { local($id) = @_; local $object = $ALF_Object{$id}; $object? $object : $id; } sub ALF_Identification { local($object) = @_; local $name = $ALF_Name{$object}; local $type = $ALF_Type{$object}; $name? $name : $type? $type : $object; } sub ALF_HierarchyInfoText { local($object,$maxlevel) = @_; local $id = &ALF_Identification($object); local $parent = $object; local $level = 0; while ($level < $maxlevel) { $level += 1; $parent = $ALF_Parent{$parent}; last unless $parent; $id = join('.',&ALF_Identification($parent),$id); } $id =~ s/\s//g; $id; } ### create design elements ### sub ALF_CreateCellReferences { local($library) = @_; foreach $cell (&ALF_FindMatchingObjects($library,'CELL')) { local $ref = $ALF_Name{$cell}; unless ($ALF_Object{$ref}) { $ALF_Object{$ref} = $cell; } } } sub ALF_CreateCellInstances { local($design,%cell) = @_; local $cell_list = &CreateArray(); foreach $key (keys %cell) { local $ref = $cell{$key}; local $object = $ALF_Object{$ref}; if ($object) { local $cell = &ALF_CopyObject($object,$design,$ref,$key); $ALF_Object{$key} = $cell; &AppendArray($cell_list,$cell); } else { print("# ALF Data Error: reference \47$ref\47 for key \47$key\47 not found in design \47$design\47\n"); } } $cell_list; } sub ALF_CreateNodes { local($design,@id) = @_; local $node_list = &CreateArray(); foreach $id (@id) { local $node = &ALF_CreateNode($design,$id); $ALF_Object{$id} = $node; &AppendArray($node_list,$node); } $node_list; } sub ALF_CreateNode { local($parent,$name) = @_; local $node = &ALF_CreateObject($parent,'NODE',$name); foreach $type ('DELAY','SLEWRATE','CAPACITANCE') { local $model = &ALF_CreateObject($node,$type); local $default = &ALF_CreateObject($model,'DEFAULT',undef,0); foreach $subtype ('RISE','FALL') { local $submodel = &ALF_CreateObject($model,$subtype); $ALF_Record{$submodel} = &CreateArray(); } } $node; } ### create design constraints ### sub ALF_CreateConstraint { local($node,$type,$subtype,$result,%condition) = @_; $node = &ALF_Object($node); local $model = &ALF_FindMatchingObject($node,$type); local $submodel = &ALF_FindMatchingObject($model,$subtype); local $data = &ALF_AppendRecord($ALF_Record{$submodel}); &ALF_UpdateRecord($data,$result,%condition); } ### create connectivity and calculation graph for nodes ### sub ALF_CreateSum { local($model,@nodes) = @_; local $type = $ALF_Type{$model}; foreach $subtype ('RISE','FALL') { local $sum = &ALF_FindMatchingObject($model,$subtype); local @arg; foreach $node (@nodes) { local $arg = &ALF_FindMatchingObject(&ALF_FindMatchingObject($node,$type),$subtype); $arg[$#arg+1] = $arg if defined($arg); } if ($#arg > 0) { local $header = &ALF_CreateObject($sum,'HEADER'); local @sum; foreach $arg (@arg) { local $name = &AutoName; local $addend = &ALF_CreateObject($header,$type,$name); $ALF_Link{$addend} = $arg; $sum[$#sum+1] = $name; } &ALF_CreateObject($sum,'EQUATION',undef,&CreateArray(split(/\s/,join(' + ',@sum)))); } elsif ($#arg == 0) { $ALF_Link{$sum} = $arg[0]; } else { $ALF_Value{$sum} = 0; } } } sub ALF_LinkNodes { local($driver,@receivers) = @_; foreach $type ('DELAY','SLEWRATE') { foreach $receiver (@receivers) { local $model = &ALF_FindMatchingObject($receiver,$type); &ALF_CreateSum($model,$driver); } } &ALF_CreateSum(&ALF_FindMatchingObject($driver,'CAPACITANCE'),@receivers); } sub ALF_LinkNodeModel { local($node,$type) = @_; $node = &ALF_Object($node); local $model = &ALF_FindMatchingObject($node,$type); if ($model) { foreach $subtype ('RISE','FALL') { local $submodel = &ALF_FindMatchingObject($model,$subtype); local $record = $ALF_Record{$submodel}; $ALF_EvaluationMethod{$record} = 'sum'; } } } ### Create connectivity and calculation graph for cells ### sub ALF_LinkCell { local($cell,%connect) = @_; $cell = &ALF_Object($cell); print("# ALF Data Info: creating links in cell:\t",&ALF_ObjectInfoText($cell),"\n") if $ALF_Debug; foreach $key (keys %connect) { local $pin = &ALF_FindMatchingObject($cell,'PIN',$key); if (defined($pin)) { $ALF_Link{$pin} = &ALF_Object($connect{$key}); local $pinmodel = &ALF_FindMatchingObject($pin,'CAPACITANCE'); &ALF_LinkPinModel($pinmodel) if $pinmodel; } else { print("# ALF Data Error: no pin named $key found in cell:\t",&ALF_ObjectInfoText($cell),"\n"); } } foreach $vector (&ALF_FindMatchingObjects($cell,'VECTOR')) { print("# ALF Data Info: creating links for models in vector:\t",&ALF_ObjectInfoText($vector),"\n") if $ALF_Debug; local $expression = $ALF_Expression{$vector}; local $models = &CreateArray(); &ALF_SearchForObjects($models,$vector,'ALF_IsFullArithmeticModel'); foreach $model (&Array($models)) { print("# ALF Data Info: searching link for model:\t",&ALF_ObjectInfoText($model),"\n") if $ALF_Debug; &ALF_LinkVectorModel($model,$expression); local $header = &ALF_FindMatchingObject($model,'HEADER'); foreach $arg (&Array($ALF_Children{$header})) { &ALF_LinkVectorModel($arg,$expression); print("# ALF Data Info: searching link for model argument:\t",&ALF_ObjectInfoText($arg),"\n") if $ALF_Debug; } } } } sub ALF_LinkVectorModel { local($model,$expression) = @_; local $is_arg = &StringMatch($ALF_Type{$ALF_Parent{$model}},'HEADER'); local $designation = $is_arg? 'model argument' : 'model'; local ($pin,$node,$ref); if ( ($pin = &ALF_FindMatchingObject($model,'PIN')) && ($node = $ALF_Link{$ALF_Link{$pin}}) && ($ref = &ALF_FindMatchingObject($node,$ALF_Type{$model})) ) { print("# ALF Data Info: pointer to link found for $designation:\t",&ALF_ObjectInfoText($model),"\n") if $ALF_Debug; local $edge = &ALF_FindEdgeLiteral($expression,$ALF_Value{$pin}); local $link; if ($link = &ALF_IsRisingEdge ($edge)? &ALF_FindMatchingObject($ref,'RISE') : &ALF_IsFallingEdge($edge)? &ALF_FindMatchingObject($ref,'FALL') : undef) { print("# ALF Data Info: $designation $model has link:\t",&ALF_ObjectInfoText($link),"\n") if $ALF_Debug; if ($is_arg) { $ALF_Link{$model} = $link; } else { &ALF_AppendRecord($ALF_Record{$link},$model); } } elsif ($link = &ALF_FindMatchingObject($ref,'DEFAULT')) { print("# ALF Data Warning: $designation $model has default link:\t",&ALF_ObjectInfoText($link),"\n"); if ($is_arg) { $ALF_Link{$model} = $link; } else { &ALF_AppendRecord($ALF_Record{$link},$model); } } else { print("# ALF Data Error: $designation $model has no link\n"); } } } sub ALF_LinkPinModel { local($pin_model) = @_; local $node = $ALF_Link{$ALF_Parent{$pin_model}}; local $node_model = &ALF_FindMatchingObject($node,$ALF_Type{$pin_model}); foreach $subtype ('RISE','FALL') { local $found_submodel = &ALF_FindMatchingObject($pin_model,$subtype); local $pin_submodel = $found_submodel? $found_submodel : $pin_model; local $node_submodel = &ALF_FindMatchingObject($node_model,$subtype); &ALF_AppendRecord($ALF_Record{$node_submodel},$pin_submodel); print("# ALF Data Info: linking pin model\t",&ALF_ObjectInfoText($pin_submodel),"\n") if $ALF_Debug; print("# ALF Data Info: linked pin model $pin_submodel to node\t",&ALF_ObjectInfoText($node_submodel),"\n") if $ALF_Debug; } } ### analysis engine ### sub ALF_LibraryPreparation { local ($library) = @_; print("# System Message:\tstarted library preparation\t",&DateTime,"\n"); &ALF_FlattenObject($library); &ALF_CreateCellReferences($library); print("# System Message:\tfinished library preparation\t",&DateTime,"\n"); } sub ALF_CircuitAnalysis { local ($design,$ruleset,$netlist,$constraint,$method,@modeltype) = @_; print("# System Message:\tstarted circuit analysis\t",&DateTime,"\n"); local ($cell_list,$node_list,$connect_list) = &Eval($netlist,$design); local %cell_list = &Assoc($cell_list); local @cell_list = &AssocKeys($cell_list); local @node_list = &Array($node_list); &ALF_CreateCellInstances($design,%cell_list); &ALF_CreateNodes($design,@node_list); print("# System Message:\tcreated design elements \t",&DateTime,"\n"); &ALF_LinkObjects($ruleset,$design,'CELL','WIRE'); print("# System Message:\tcreated internal connectivity\t",&DateTime,"\n"); foreach $cell (@cell_list) { $cell = &ALF_Object($cell); local $connect = &AssocVal($connect_list,$ALF_Name{$cell}); &ALF_LinkCell($cell,&Assoc($connect)); } foreach $node (@node_list) { $node = &ALF_Object($node); &ALF_LinkNodeModel($node,'CAPACITANCE'); } print("# System Message:\tcreated external connectivity\t",&DateTime,"\n"); &Eval($constraint); print("# System Message:\tcreated evaluation constraints\t",&DateTime,"\n"); local $models = &CreateArray(); foreach $modeltype (@modeltype) { foreach $cell (@cell_list) { $cell = &ALF_Object($cell); &ALF_SearchForObjects($models,$cell,'ALF_ObjectMatch',$modeltype); } } print("# System Message:\tidentified evaluation targets\t",&DateTime,"\n\n"); foreach $model (&Array($models)) { local $id = &ALF_HierarchyInfoText($model,5); local $result = &ALF_Calculate($model,$method); print("#\tevaluation result for model $model: $id = $result\n"); } print("# System Message:\tfinished circuit analysis\t",&DateTime,"\n"); } 1;