### global variables ### %ALF_InstanceReference = (); # ( inst -> ref ) %ALF_InstanceConnect = (); # ( inst -> connect ) where connect = ( pin -> node ) %ALF_InstanceList = (); # ( module -> list of inst ) ### handling nodes ### sub ALF_NodeList { local(@inst_list) = @_; # extract value for each ( inst -> ( pin -> node ) ) local @node_list; foreach $inst (@inst_list) { #print("inst=$inst\n"); local %connect = &Assoc($ALF_InstanceConnect{$inst}); foreach $pin (keys %connect) { local $node = $connect{$pin}; #print("\tpin=$pin\tnode=$node\n"); $node_list[$#node_list+1] = $node unless defined(&FindArrayKey('node_list',$node)); } } @node_list; } sub ALF_BusList { local(@pin_list) = @_; local (@bus_list,%lsb,%msb); foreach $pin (@pin_list) { local @pin = split(/\./,$pin); if (&ALF_LexicalMatch('indexed_identifier',$pin[$#pin])) { local($name,$msb,$lsb) = &ALF_BusBits($pin); if (defined(&FindArrayKey('bus_list',$name))) { local $lsb0 = $lsb{$name}; local $msb0 = $msb{$name}; $lsb{$name} = $lsb if ($lsb < $lsb0); $msb{$name} = $msb if ($msb > $msb0); } else { $msb{$name} = $msb; $lsb{$name} = $lsb; $bus_list[$#bus_list+1] = $name; } } else { $bus_list[$#bus_list+1] = $pin; } } local %bus_list; foreach $pin (@bus_list) { local $msb = $msb{$pin}; local $lsb = $lsb{$pin}; $bus_list{$pin} = (defined($msb) && defined($lsb))? "[$msb:$lsb]" : undef; } %bus_list; } sub ALF_BusBits { local($pin) = @_; local ($name,$index) = split(/[\[\]]/,$pin); local ($index1,$index2) = split(/:/,$index); local ($msb,$lsb); if (defined($index1) && defined($index2)) { if ($index1 < $index2) { $msb = $index2; $lsb = $index1; } else { $msb = $index1; $lsb = $index2; } } elsif (defined($index)) { $msb = $index; $lsb = $index; } ($name,$msb,$lsb); } ### create ALF data structure for netlist ### sub ALF_CreateNetlist { local($design,@libraries) = @_; print("# ALF Message:\tstarted creating netlist models ",&DateTime,"\n"); local @modules = sort( ByDescendingLength (keys %ALF_InstanceList) ); #print("modules = (@modules)\n"); local @cell; foreach $module (@modules) { $cell[$#cell+1] = &ALF_CreateBlock($design,$module); } foreach $cell (@cell) { &ALF_LinkBlock($cell,$design,@libraries); } print("# ALF Message:\tfinished creating netlist models ",&DateTime,"\n"); } sub ALF_CreateBlock { local($object,$module) = @_; local $cell = &ALF_CreateObject($object,'CELL',$module); local %pin_connect = &Assoc($ALF_InstanceConnect{$module}); local %bus_list = &ALF_BusList(keys %pin_connect); foreach $pin (keys %bus_list) { $external_pin = &ALF_CreateObject($cell,'PIN',$pin,undef,'ALF_1stIndex',$bus_list{$pin}); &ALF_CreateObject($external_pin,'DIRECTION',undef,'input'); } local @inst_list = &Array($ALF_InstanceList{$module}); local @internal_nodes; foreach $internal_node (&ALF_ComponentsInside($module,&ALF_NodeList(@inst_list))) { local @internal_node = &ALF_SubPath($internal_node,split(/\./,$module)); $internal_nodes[$#internal_nodes+1] = $internal_node[0]? join('.',@internal_node) : $internal_node; } local %internal_bus_list = &ALF_BusList(@internal_nodes); #print("@internal_nodes=(@internal_nodes)\n"); foreach $node (keys %internal_bus_list) { local $bus = $internal_bus_list{$node}; #print("\tnode=$node\tbus=$bus\n"); #if defined($bus); if (defined($bus)) { $internal_pin = &ALF_CreateObject($cell,'PIN',$node,undef,'ALF_1stIndex',$bus); &ALF_CreateObject($internal_pin,'DIRECTION',undef,'none'); } } local $structure = &ALF_CreateObject(&ALF_CreateObject($cell,'FUNCTION'),'STRUCTURE'); foreach $inst (@inst_list) { &ALF_CreateNetlistComponent($structure,$inst,$module); } $cell; } sub ALF_CreateNetlistComponent { local($parent,$inst,$root) = @_; local @root = split(/\./,$root); local @subpath = &ALF_SubPath($inst,@root); local $name = $subpath[0]? join('.',@subpath) : $inst; $name = "\\$name" unless &ALF_LexicalMatch('identifier',$name); #print("root=$root\tinst=$inst\tsubpath=(@subpath)\tname=$name\n"); local $object = &ALF_CreateObject($parent,$ALF_InstanceReference{$inst},$name); local $connect = $ALF_InstanceConnect{$inst}; local %connect = defined($connect)? &Assoc($connect) : undef; if (defined(%connect)) { foreach $pin (keys %connect) { local @connect = &ALF_SubPath($connect{$pin},@root); local $value = $connect[0]? join('.',@connect) : $connect{$pin}; $value = "\\$value" unless (&ALF_LexicalMatch('identifier',$value) || &ALF_LexicalMatch('bit_literal',$value)); &ALF_CreateObject($object,$pin,undef,$value); } } else { print("# ALF Data Warning: unconnected instance\t",&ALF_ObjectInfoText($object),"\n"); } $object; } sub ALF_LinkBlock { local($cell,@library) = @_; local $structure = &ALF_FindMatchingObject(&ALF_FindMatchingObject($cell,'FUNCTION'),'STRUCTURE'); if (defined($structure)) { foreach $component (&Array($ALF_Children{$structure})) { &ALF_LinkNetlistComponent($component,@library); } } else { print("# ALF Data Warning: no netlist view for block\t",&ALF_ObjectInfoText($cell),"\n"); } } sub ALF_LinkNetlistComponent { local($component,@library) = @_; local $cell_name = $ALF_Type{$component}; local $cell; foreach $library (@library) { # $cell = &ALF_SearchForObject($library,'ALF_ObjectMatch','CELL',$cell_name); $cell = &ALF_FindMatchingObject($library,'CELL',$cell_name); last if defined($cell); } if (defined($cell)) { print("# ALF Data Info: found reference for netlist component $component:\t",&ALF_ObjectInfoText($cell),"\n") if $ALF_Debug; $ALF_Link{$component} = $cell; foreach $connect (&Array($ALF_Children{$component})) { local ($pin_name) = &ALF_BusBits($ALF_Type{$connect}); local $pin = &ALF_FindMatchingObject($cell,'PIN',$pin_name); if (defined($pin)) { $ALF_Link{$connect} = $pin; local ($node_name) = &ALF_BusBits($ALF_Value{$connect}); local $node = &ALF_FindMatchingObject(&ALF_FindAncestor($component,'CELL'),'PIN',$node_name); if ($node) { local $pin_dir = &ALF_FindMatchingObject($pin,'DIRECTION'); local $node_dir = &ALF_FindMatchingObject($node,'DIRECTION'); $ALF_Value{$node_dir} = &ALF_UpdateDirection($ALF_Value{$node_dir},$ALF_Value{$pin_dir}); # } elsif (&ALF_LexicalMatch('bit_literal',$node_name)) { # } else { # print("# ALF Data Error: component has ill-defined netlist connection\t",&ALF_ObjectInfoText($component),"\n"); # print("# ALF Data Error: no declared pin for netlist connection\t",&ALF_ObjectInfoText($connect),"\n"); } } else { print("# ALF Data Error: component has ill-defined netlist connection\t",&ALF_ObjectInfoText($component),"\n"); print("# ALF Data Error: no reference pin for netlist connection\t",&ALF_ObjectInfoText($connect),"\n"); } } } else { print("# ALF Data Error: no reference cell for netlist component\t",&ALF_ObjectInfoText($component),"\n"); } } sub ALF_UpdateDirection { local($node_dir,$pin_dir) = @_; &StringMatch($node_dir,$pin_dir)? $pin_dir : &StringMatch($node_dir,'none')? 'none' : &StringMatch($pin_dir,'both')? 'both' : &StringMatch($pin_dir,'output')? 'output' : 'input'; } ### extract data from data structure ### sub ALF_ExtractInstanceReference { local($object) = @_; local %inst_ref; foreach $inst (&Array($ALF_Children{$object})) { local $inst_type = $ALF_Type{$inst}; local $inst_name = $ALF_Name{$inst}; if (defined($inst_ref{$inst_name})) { print("# ALF Data Error: instance name is not unique\t",&ALF_ObjectInfoText($inst),"\n"); } else { $inst_ref{$inst_name} = $inst_type; } } %inst_ref; } sub ALF_ExtractInstanceConnect { local($object) = @_; local %inst_connect; foreach $inst (&Array($ALF_Children{$object})) { local $inst_name = $ALF_Name{$inst}; local $inst_connect = &CreateAssoc(); foreach $connect (&Array($ALF_Children{$inst})) { local $pin = $ALF_Type{$connect}; local $node = $ALF_Value{$connect}; if (defined(&AssocVal($inst_connect,$pin))) { print("# ALF Data Error: illegal redefined connection \42$pin = $node\42\t",&ALF_ObjectInfoText($inst),"\n"); } else { &AppendAssoc($inst_connect,$pin,$node); } } $inst_connect{$inst_name} = $inst_connect; } %inst_connect; } sub ALF_ExtractInstanceList { local($object) = @_; local @inst_list; foreach $inst (&Array($ALF_Children{$object})) { $inst_list[$#inst_list+1] = $ALF_Name{$inst}; } @inst_list; } sub ALF_ExtractNodeList { local($object) = @_; local @node_list; foreach $inst (&Array($ALF_Children{$object})) { foreach $connect (&Array($ALF_Children{$inst})) { local $node = $ALF_Value{$connect}; $node_list[$#node_list+1] = $node unless defined(&FindArrayKey('node_list',$node)); } } @node_list; } ### process hierarchy ### sub ALF_SubPath { local($component,@path) = @_; local @component = split(/\./,$component); local $inside = 1; for $i (0..$#path) { $inside = ($path[$i] eq $component[$i]); last unless $inside; } ($inside && $#component > $#path)? &SubArray('component',$#path+1,$#component) : undef; } sub ALF_RootComponent { local(@components) = @_; local ($top,$bottom); foreach $component (@components) { ($top,$bottom) = split(/\./,$component); last if (defined($bottom)); } $bottom? $top : undef; } sub ALF_FullPathComponents { local($top,@components) = @_; local @list; foreach $component (@components) { $list[$#list+1] = join('.',$top,$component); } defined($top)? @list : @components; } sub ALF_BranchComponents { local($top,@components) = @_; local @list; local @top = split(/\./,$top); foreach $component (@components) { local ($new) = &ALF_SubPath($component,@top); $list[$#list+1] = $new if (defined($new) && !defined(&FindArrayKey('list',$new))); } @list; } sub ALF_LeafComponents { local($top,@components) = @_; local @list; local @top = split(/\./,$top); foreach $component (@components) { local $new = join('.',&ALF_SubPath($component,@top)); $list[$#list+1] = $new if defined($new); } @list; } sub ALF_ComponentsInside { local($top,@components) = @_; local @list; local @top = split(/\./,$top); foreach $component (@components) { $list[$#list+1] = $component if &ALF_SubPath($component,@top); } @list; } sub ALF_ComponentsOutside { local($top,@components) = @_; local @list; local @top = split(/\./,$top); foreach $component (@components) { $list[$#list+1] = $component unless &ALF_SubPath($component,@top); } @list; } sub ALF_CreateHierarchyModule { local($module,@pins) = @_; local %pin_connect; foreach $pin (@pins) { $pin_connect{$pin} = $pin if &ALF_LexicalMatch('identifier',$pin); } #print("module=$module\tpin_connect=(",join(' ',%pin_connect),")\n"); ($module,%pin_connect); } sub ALF_CreateHierarchy { local($top,@inst) = @_; local @subhier = &ALF_BranchComponents($top,@inst); #print("top=$top\tsubhier=(@subhier)\n"); if (defined($top)) { local @subinst = &ALF_ComponentsInside($top,@inst); #print("\tsubinst=(@subinst)\n"); foreach $subhier (@subhier) { local $subtop = join('.',$top,$subhier); local $connect = $ALF_InstanceConnect{$subtop}; &ALF_CreateHierarchy($subtop,@subinst) unless $connect; } local @instlist = &ALF_FullPathComponents($top,@subhier); $ALF_InstanceList{$top} = &CreateArray(@instlist); #print("ALF_InstanceList{$top} = (",join(' ',&Array($ALF_InstanceList{$top})),")\n"); local @nodes = &ALF_NodeList(@instlist); local @pins = &ALF_ComponentsOutside($top,@nodes); #print("\tnodes=(@nodes)\tpins=(@pins)\n"); local ($inst,%pin_connect) = &ALF_CreateHierarchyModule($top,@pins); $ALF_InstanceReference{$inst} = $top; $ALF_InstanceConnect{$inst} = &CreateAssoc(%pin_connect); } else { $top = &AutoName; $ALF_InstanceList{$top} = &CreateArray(&ALF_FullPathComponents(undef,@subhier)); } $top; } 1;