Data update
This commit is contained in:
parent
5150844a7d
commit
4bb20c9b71
7735 changed files with 38060 additions and 199180 deletions
|
|
@ -1,52 +0,0 @@
|
|||
with Ada.Containers.Vectors; use Ada.Containers;
|
||||
|
||||
package Digraphs is
|
||||
|
||||
type Node_Idx_With_Null is new Natural;
|
||||
subtype Node_Index is Node_Idx_With_Null range 1 .. Node_Idx_With_Null'Last;
|
||||
-- a Node_Index is a number from 1, 2, 3, ... and the representative of a node
|
||||
|
||||
type Graph_Type is tagged private;
|
||||
|
||||
-- make sure Node is in Graph (possibly without connections)
|
||||
procedure Add_Node
|
||||
(Graph: in out Graph_Type'Class; Node: Node_Index);
|
||||
|
||||
-- insert an edge From->To into Graph; do nothing if already there
|
||||
procedure Add_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index);
|
||||
|
||||
-- get the largest Node_Index used in any Add_Node or Add_Connection op.
|
||||
-- iterate over all nodes of Graph: "for I in 1 .. Graph.Node_Count loop ..."
|
||||
function Node_Count(Graph: Graph_Type) return Node_Idx_With_Null;
|
||||
|
||||
-- remove an edge From->To from Fraph; do nothing if not there
|
||||
-- Graph.Node_Count is not changed
|
||||
procedure Del_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index);
|
||||
|
||||
-- check if an edge From->to exists in Graph
|
||||
function Connected
|
||||
(Graph: Graph_Type; From, To: Node_Index) return Boolean;
|
||||
|
||||
-- data structure to store a list of nodes
|
||||
package Node_Vec is new Vectors(Positive, Node_Index);
|
||||
|
||||
-- get a list of all nodes From->Somewhere in Graph
|
||||
function All_Connections
|
||||
(Graph: Graph_Type; From: Node_Index) return Node_Vec.Vector;
|
||||
|
||||
Graph_Is_Cyclic: exception;
|
||||
|
||||
-- a depth-first search to find a topological sorting of the nodes
|
||||
-- raises Graph_Is_Cyclic if no topological sorting is possible
|
||||
function Top_Sort
|
||||
(Graph: Graph_Type) return Node_Vec.Vector;
|
||||
|
||||
private
|
||||
|
||||
package Conn_Vec is new Vectors(Node_Index, Node_Vec.Vector, Node_Vec."=");
|
||||
|
||||
type Graph_Type is new Conn_Vec.Vector with null record;
|
||||
|
||||
end Digraphs;
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
package body Digraphs is
|
||||
|
||||
function Node_Count(Graph: Graph_Type) return Node_Idx_With_Null is
|
||||
begin
|
||||
return Node_Idx_With_Null(Graph.Length);
|
||||
end Node_Count;
|
||||
|
||||
procedure Add_Node(Graph: in out Graph_Type'Class; Node: Node_Index) is
|
||||
begin
|
||||
for I in Node_Index range Graph.Node_Count+1 .. Node loop
|
||||
Graph.Append(Node_Vec.Empty_Vector);
|
||||
end loop;
|
||||
end Add_Node;
|
||||
|
||||
procedure Add_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index) is
|
||||
begin
|
||||
Graph.Add_Node(Node_Index'Max(From, To));
|
||||
declare
|
||||
Connection_List: Node_Vec.Vector := Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) >= To then
|
||||
if Connection_List.Element(I) = To then
|
||||
return; -- if To is already there, don't add it a second time
|
||||
else -- I is the first index with Element(I)>To, insert To here
|
||||
Connection_List.Insert(Before => I, New_Item => To);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return;
|
||||
end if;
|
||||
end if;
|
||||
end loop;
|
||||
-- there was no I with no Element(I) > To, so insert To at the end
|
||||
Connection_List.Append(To);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return;
|
||||
end;
|
||||
end Add_Connection;
|
||||
|
||||
procedure Del_Connection
|
||||
(Graph: in out Graph_Type'Class; From, To: Node_Index) is
|
||||
Connection_List: Node_Vec.Vector := Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) = To then
|
||||
Connection_List.Delete(I);
|
||||
Graph.Replace_Element(From, Connection_List);
|
||||
return; -- we are done
|
||||
end if;
|
||||
end loop;
|
||||
end Del_Connection;
|
||||
|
||||
function Connected
|
||||
(Graph: Graph_Type; From, To: Node_Index) return Boolean is
|
||||
Connection_List: Node_Vec.Vector renames Graph.Element(From);
|
||||
begin
|
||||
for I in Connection_List.First_Index .. Connection_List.Last_Index loop
|
||||
if Connection_List.Element(I) = To then
|
||||
return True;
|
||||
end if;
|
||||
end loop;
|
||||
return False;
|
||||
end Connected;
|
||||
|
||||
function All_Connections
|
||||
(Graph: Graph_Type; From: Node_Index) return Node_Vec.Vector is
|
||||
begin
|
||||
return Graph.Element(From);
|
||||
end All_Connections;
|
||||
|
||||
function Top_Sort
|
||||
(Graph: Graph_Type) return Node_Vec.Vector is
|
||||
|
||||
Result: Node_Vec.Vector;
|
||||
Visited: array(1 .. Graph.Node_Count) of Boolean := (others => False);
|
||||
Active: array(1 .. Graph.Node_Count) of Boolean := (others => False);
|
||||
|
||||
procedure Visit(Node: Node_Index) is
|
||||
begin
|
||||
if not Visited(Node) then
|
||||
Visited(Node) := True;
|
||||
Active(Node) := True;
|
||||
declare
|
||||
Cons: Node_Vec.Vector := All_Connections(Graph, Node);
|
||||
begin
|
||||
for Idx in Cons.First_Index .. Cons.Last_Index loop
|
||||
Visit(Cons.Element(Idx));
|
||||
end loop;
|
||||
end;
|
||||
Active(Node) := False;
|
||||
Result.Append(Node);
|
||||
else
|
||||
if Active(Node) then
|
||||
raise Constraint_Error with "Graph is Cyclic";
|
||||
end if;
|
||||
end if;
|
||||
end Visit;
|
||||
|
||||
begin
|
||||
for Some_Node in Visited'Range loop
|
||||
Visit(Some_Node);
|
||||
end loop;
|
||||
return Result;
|
||||
end Top_Sort;
|
||||
|
||||
end Digraphs;
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
private with Ada.Containers.Indefinite_Vectors;
|
||||
|
||||
generic
|
||||
type Index_Type_With_Null is new Natural;
|
||||
package Set_Of_Names is
|
||||
subtype Index_Type is Index_Type_With_Null
|
||||
range 1 .. Index_Type_With_Null'Last;
|
||||
-- manage a set of strings;
|
||||
-- each string in the set is assigned a unique index of type Index_Type
|
||||
|
||||
type Set is tagged private;
|
||||
|
||||
-- inserts Name into Names; do nothing if already there;
|
||||
procedure Add(Names: in out Set; Name: String);
|
||||
|
||||
-- Same operation, additionally emiting Index=Names.Idx(Name)
|
||||
procedure Add(Names: in out Set; Name: String; Index: out Index_Type);
|
||||
|
||||
-- remove Name from Names; do nothing if not found
|
||||
-- the removal may change the index of other strings in Names
|
||||
procedure Sub(Names: in out Set; Name: String);
|
||||
|
||||
-- returns the unique index of Name in Set; or 0 if Name is not there
|
||||
function Idx(Names: Set; Name: String) return Index_Type_With_Null;
|
||||
|
||||
-- returns the unique name of Index;
|
||||
function Name(Names: Set; Index: Index_Type) return String;
|
||||
|
||||
-- first index, last index and total number of names in set
|
||||
-- to iterate over Names, use "for I in Names.Start .. Names.Stop loop ...
|
||||
function Start(Names: Set) return Index_Type;
|
||||
function Stop(Names: Set) return Index_Type_With_Null;
|
||||
function Size(Names: Set) return Index_Type_With_Null;
|
||||
|
||||
private
|
||||
|
||||
package Vecs is new Ada.Containers.Indefinite_Vectors
|
||||
(Index_Type => Index_Type, Element_Type => String);
|
||||
|
||||
type Set is new Vecs.Vector with null record;
|
||||
|
||||
end Set_Of_Names;
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
package body Set_Of_Names is
|
||||
|
||||
use type Ada.Containers.Count_Type, Vecs.Cursor;
|
||||
|
||||
function Start(Names: Set) return Index_Type is
|
||||
begin
|
||||
if Names.Length = 0 then
|
||||
return 1;
|
||||
else
|
||||
return Names.First_Index;
|
||||
end if;
|
||||
end Start;
|
||||
|
||||
function Stop(Names: Set) return Index_Type_With_Null is
|
||||
begin
|
||||
if Names.Length=0 then
|
||||
return 0;
|
||||
else
|
||||
return Names.Last_Index;
|
||||
end if;
|
||||
end Stop;
|
||||
|
||||
function Size(Names: Set) return Index_Type_With_Null is
|
||||
begin
|
||||
return Index_Type_With_Null(Names.Length);
|
||||
end Size;
|
||||
|
||||
procedure Add(Names: in out Set; Name: String; Index: out Index_Type) is
|
||||
I: Index_Type_With_Null := Names.Idx(Name);
|
||||
begin
|
||||
if I = 0 then -- Name is not yet in Set
|
||||
Names.Append(Name);
|
||||
Index := Names.Stop;
|
||||
else
|
||||
Index := I;
|
||||
end if;
|
||||
end Add;
|
||||
|
||||
procedure Add(Names: in out Set; Name: String) is
|
||||
I: Index_Type;
|
||||
begin
|
||||
Names.Add(Name, I);
|
||||
end Add;
|
||||
|
||||
procedure Sub(Names: in out Set; Name: String) is
|
||||
I: Index_Type_With_Null := Names.Idx(Name);
|
||||
begin
|
||||
if I /= 0 then -- Name is in set
|
||||
Names.Delete(I);
|
||||
end if;
|
||||
end Sub;
|
||||
|
||||
function Idx(Names: Set; Name: String) return Index_Type_With_Null is
|
||||
begin
|
||||
for I in Names.First_Index .. Names.Last_Index loop
|
||||
if Names.Element(I) = Name then
|
||||
return I;
|
||||
end if;
|
||||
end loop;
|
||||
return 0;
|
||||
end Idx;
|
||||
|
||||
function Name(Names: Set; Index: Index_Type) return String is
|
||||
begin
|
||||
return Names.Element(Index);
|
||||
end Name;
|
||||
|
||||
end Set_Of_Names;
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
with Ada.Text_IO, Digraphs, Set_Of_Names, Ada.Command_Line;
|
||||
|
||||
procedure Toposort is
|
||||
|
||||
-- shortcuts for package names, intantiation of generic package
|
||||
package TIO renames Ada.Text_IO;
|
||||
package DG renames Digraphs;
|
||||
package SN is new Set_Of_Names(DG.Node_Idx_With_Null);
|
||||
|
||||
-- reat the graph from the file with the given Filename
|
||||
procedure Read(Filename: String; G: out DG.Graph_Type; N: out SN.Set) is
|
||||
|
||||
-- finds the first word in S(Start .. S'Last), delimited by spaces
|
||||
procedure Find_Token(S: String; Start: Positive;
|
||||
First: out Positive; Last: out Natural) is
|
||||
|
||||
begin
|
||||
First := Start;
|
||||
while First <= S'Last and then S(First)= ' ' loop
|
||||
First := First + 1;
|
||||
end loop;
|
||||
Last := First-1;
|
||||
while Last < S'Last and then S(Last+1) /= ' ' loop
|
||||
Last := Last + 1;
|
||||
end loop;
|
||||
end Find_Token;
|
||||
|
||||
File: TIO.File_Type;
|
||||
begin
|
||||
TIO.Open(File, TIO.In_File, Filename);
|
||||
TIO.Skip_Line(File, 2);
|
||||
-- the first two lines contain header and "===...==="
|
||||
while not TIO.End_Of_File(File) loop
|
||||
declare
|
||||
Line: String := TIO.Get_Line(File);
|
||||
First: Positive;
|
||||
Last: Natural;
|
||||
To, From: DG.Node_Index;
|
||||
begin
|
||||
Find_Token(Line, Line'First, First, Last);
|
||||
if Last >= First then
|
||||
N.Add(Line(First .. Last), From);
|
||||
G.Add_Node(From);
|
||||
loop
|
||||
Find_Token(Line, Last+1, First, Last);
|
||||
exit when Last < First;
|
||||
N.Add(Line(First .. Last), To);
|
||||
G.Add_Connection(From, To);
|
||||
end loop;
|
||||
end if;
|
||||
end;
|
||||
end loop;
|
||||
TIO.Close(File);
|
||||
end Read;
|
||||
|
||||
Graph: DG.Graph_Type;
|
||||
Names: SN.Set;
|
||||
|
||||
begin
|
||||
Read(Ada.Command_Line.Argument(1), Graph, Names);
|
||||
|
||||
-- eliminat self-cycles
|
||||
for Start in 1 .. Graph.Node_Count loop
|
||||
Graph.Del_Connection(Start, Start);
|
||||
end loop;
|
||||
|
||||
-- perform the topological sort and output the result
|
||||
declare
|
||||
Result: DG.Node_Vec.Vector;
|
||||
begin
|
||||
Result := Graph.Top_Sort;
|
||||
for Index in Result.First_Index .. Result.Last_Index loop
|
||||
TIO.Put(Names.Name(Result.Element(Index)));
|
||||
if Index < Result.Last_Index then
|
||||
TIO.Put(" -> ");
|
||||
end if;
|
||||
end loop;
|
||||
TIO.New_Line;
|
||||
exception
|
||||
when DG.Graph_Is_Cyclic =>
|
||||
TIO.Put_Line("There is no topological sorting -- the Graph is cyclic!");
|
||||
end;
|
||||
end Toposort;
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#Input Data
|
||||
$a=@"
|
||||
des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee
|
||||
dw01 ieee dw01 dware gtech
|
||||
dw02 ieee dw02 dware
|
||||
dw03 std synopsys dware dw03 dw02 dw01 ieee gtech
|
||||
dw04 dw04 ieee dw01 dware gtech
|
||||
dw05 dw05 ieee dware
|
||||
dw06 dw06 ieee dware
|
||||
dw07 ieee dware
|
||||
dware ieee dware
|
||||
gtech ieee gtech
|
||||
ramlib std ieee
|
||||
std_cell_lib ieee std_cell_lib
|
||||
synopsys
|
||||
"@
|
||||
#Convert to Object[]
|
||||
$c = switch ( $a.split([char] 10) ) {
|
||||
$_ {
|
||||
$b=$_.split(' ')
|
||||
New-Object PSObject -Property @{
|
||||
Library = $b[0]
|
||||
"Library Dependencies" = @( $( $b[1..($b.length-1)] | Where-Object { $_ -match '\w' } ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
#Add pure dependencies
|
||||
$c | ForEach-Object {
|
||||
$_."Library Dependencies" | Where-Object {
|
||||
$d=$_
|
||||
$(:andl foreach($i in $c) {
|
||||
if($d -match $i.Library) {
|
||||
$false
|
||||
break andl
|
||||
}
|
||||
}) -eq $null
|
||||
} | ForEach-Object {
|
||||
$c+=New-Object PSObject -Property @{
|
||||
Library=$_
|
||||
"Library Dependencies"=@()
|
||||
}
|
||||
}
|
||||
}
|
||||
#Associate with a dependency value
|
||||
##Initial Dependency Value
|
||||
$d = $c | Sort Library | Select-Object Library,"Library Dependencies",@{
|
||||
Name="Dep Value"
|
||||
Expression={
|
||||
1
|
||||
}
|
||||
}
|
||||
##Modify Dependency Value, perform check for incorrect dependency
|
||||
##Dep Value is determined by a parent child relationship, if a library is a parent, all libraries dependant on it are children
|
||||
for( $i=0; $i -lt $d.count; $i++ ) {
|
||||
$errmsg=""
|
||||
foreach( $j in ( 0..( $d.count - 1 ) | Where-Object { $_ -ne $i } ) ) {
|
||||
#Foreach other Child Library where this is a dependency, increase the Dep Value of the Child
|
||||
if( $( :orl foreach( $k in $d[$j]."Library Dependencies" ) {
|
||||
if( $k -match $d[$i].Library ) {
|
||||
foreach( $n in $d[$i]."Library Dependencies" ) {
|
||||
if( $n -match $d[$j].Library ) {
|
||||
$errmsg="Error Cyclic Dependency {0}<->{1}" -f $d[$i].Library, $d[$j].Library
|
||||
break
|
||||
}
|
||||
}
|
||||
$true
|
||||
break orl
|
||||
}
|
||||
} ) ) {
|
||||
#If the child has already been processed, increase the Dep Value of its children
|
||||
if( $j -lt $i ) {
|
||||
foreach( $l in ( 0..( $d.count - 1 ) | Where-Object { $_ -ne $j } ) ) {
|
||||
if( $( :orl2 foreach( $m in $d[$l]."Library Dependencies" ) {
|
||||
if( $m -match $d[$j].Library ) {
|
||||
$true
|
||||
break orl2
|
||||
}
|
||||
} ) ) {
|
||||
$d[$l]."Dep Value"+=$d[$i]."Dep Value"
|
||||
}
|
||||
}
|
||||
}
|
||||
$d[$j]."Dep Value"+=$d[$i]."Dep Value"
|
||||
}
|
||||
if( $errmsg -ne "" ) {
|
||||
$errmsg
|
||||
$d=$null
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
#Sort and Display
|
||||
if( $d ) {
|
||||
$d | Sort "Dep Value",Library | ForEach-Object {
|
||||
"{0,-14} LIBRARY DEPENDENCIES`n{1,-14} ====================" -f "LIBRARY", "======="
|
||||
} {
|
||||
"{0,-14} $($_."Library Dependencies")" -f $_.Library
|
||||
}
|
||||
}
|
||||
|
|
@ -1,112 +1,97 @@
|
|||
use std::boxed::Box;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug)]
|
||||
struct Library<'a> {
|
||||
name: &'a str,
|
||||
children: Vec<&'a str>,
|
||||
num_parents: usize,
|
||||
}
|
||||
|
||||
fn build_libraries(input: Vec<&str>) -> HashMap<&str, Box<Library>> {
|
||||
let mut libraries: HashMap<&str, Box<Library>> = HashMap::new();
|
||||
impl<'a> Library<'a> {
|
||||
const fn new(name: &'a str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
children: Vec::new(),
|
||||
num_parents: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for input_line in input {
|
||||
let line_split = input_line.split_whitespace().collect::<Vec<&str>>();
|
||||
let name = line_split.get(0).unwrap();
|
||||
fn build_libraries<'a>(input: &'a str) -> HashMap<&'a str, Library<'a>> {
|
||||
let mut libraries: HashMap<&'a str, Library<'a>> = HashMap::new();
|
||||
|
||||
for input_line in input.lines() {
|
||||
let mut line_split = input_line.split_whitespace();
|
||||
let name = line_split.next().unwrap();
|
||||
let mut num_parents: usize = 0;
|
||||
for parent in line_split.iter().skip(1) {
|
||||
for parent in line_split {
|
||||
if parent == name {
|
||||
continue;
|
||||
}
|
||||
if !libraries.contains_key(parent) {
|
||||
libraries.insert(
|
||||
parent,
|
||||
Box::new(Library {
|
||||
name: parent,
|
||||
children: vec![name],
|
||||
num_parents: 0,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
libraries.get_mut(parent).unwrap().children.push(name);
|
||||
}
|
||||
libraries
|
||||
.entry(parent)
|
||||
.or_insert_with(|| Library::new(parent))
|
||||
.children
|
||||
.push(name);
|
||||
num_parents += 1;
|
||||
}
|
||||
|
||||
if !libraries.contains_key(name) {
|
||||
libraries.insert(
|
||||
name,
|
||||
Box::new(Library {
|
||||
name,
|
||||
children: Vec::new(),
|
||||
num_parents,
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
libraries.get_mut(name).unwrap().num_parents = num_parents;
|
||||
}
|
||||
libraries
|
||||
.entry(name)
|
||||
.or_insert_with(|| Library::new(name))
|
||||
.num_parents = num_parents;
|
||||
}
|
||||
libraries
|
||||
}
|
||||
|
||||
fn topological_sort<'a>(
|
||||
mut libraries: HashMap<&'a str, Box<Library<'a>>>,
|
||||
mut libraries: HashMap<&'a str, Library<'a>>,
|
||||
) -> Result<Vec<&'a str>, String> {
|
||||
let mut needs_processing = libraries
|
||||
.iter()
|
||||
.map(|(k, _v)| k.clone())
|
||||
.collect::<HashSet<&str>>();
|
||||
let mut needs_processing = libraries.keys().copied().collect::<HashSet<&str>>();
|
||||
let mut options: Vec<&str> = libraries
|
||||
.iter()
|
||||
.filter(|(_k, v)| v.num_parents == 0)
|
||||
.map(|(k, _v)| *k)
|
||||
.filter_map(|(k, v)| (v.num_parents == 0).then_some(*k))
|
||||
.collect();
|
||||
let mut sorted: Vec<&str> = Vec::new();
|
||||
while !options.is_empty() {
|
||||
let cur = options.pop().unwrap();
|
||||
for children in libraries
|
||||
.get_mut(cur)
|
||||
.unwrap()
|
||||
.children
|
||||
.drain(0..)
|
||||
.collect::<Vec<&str>>()
|
||||
{
|
||||
let child = libraries.get_mut(children).unwrap();
|
||||
while let Some(cur) = options.pop() {
|
||||
let children = libraries.get(cur).unwrap().children.clone();
|
||||
for child_name in children {
|
||||
let child = libraries.get_mut(child_name).unwrap();
|
||||
child.num_parents -= 1;
|
||||
if child.num_parents == 0 {
|
||||
options.push(child.name)
|
||||
options.push(child.name);
|
||||
}
|
||||
}
|
||||
sorted.push(cur);
|
||||
needs_processing.remove(cur);
|
||||
}
|
||||
match needs_processing.is_empty() {
|
||||
true => Ok(sorted),
|
||||
false => Err(format!("Cycle detected among {:?}", needs_processing)),
|
||||
if needs_processing.is_empty() {
|
||||
Ok(sorted)
|
||||
} else {
|
||||
Err(format!("Cycle detected among {needs_processing:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input: Vec<&str> = vec![
|
||||
"des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee\n",
|
||||
"dw01 ieee dw01 dware gtech dw04\n",
|
||||
"dw02 ieee dw02 dware\n",
|
||||
"dw03 std synopsys dware dw03 dw02 dw01 ieee gtech\n",
|
||||
"dw04 dw04 ieee dw01 dware gtech\n",
|
||||
"dw05 dw05 ieee dware\n",
|
||||
"dw06 dw06 ieee dware\n",
|
||||
"dw07 ieee dware\n",
|
||||
"dware ieee dware\n",
|
||||
"gtech ieee gtech\n",
|
||||
"ramlib std ieee\n",
|
||||
"std_cell_lib ieee std_cell_lib\n",
|
||||
"synopsys\n",
|
||||
];
|
||||
let input: &str = "\
|
||||
des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee\n\
|
||||
dw01 ieee dw01 dware gtech\n\
|
||||
dw02 ieee dw02 dware\n\
|
||||
dw03 std synopsys dware dw03 dw02 dw01 ieee gtech\n\
|
||||
dw04 dw04 ieee dw01 dware gtech\n\
|
||||
dw05 dw05 ieee dware\n\
|
||||
dw06 dw06 ieee dware\n\
|
||||
dw07 ieee dware\n\
|
||||
dware ieee dware\n\
|
||||
gtech ieee gtech\n\
|
||||
ramlib std ieee\n\
|
||||
std_cell_lib ieee std_cell_lib\n\
|
||||
synopsys\
|
||||
";
|
||||
|
||||
let libraries = build_libraries(input);
|
||||
match topological_sort(libraries) {
|
||||
Ok(sorted) => println!("{:?}", sorted),
|
||||
Err(msg) => println!("{:?}", msg),
|
||||
Ok(sorted) => println!("{sorted:?}"),
|
||||
Err(msg) => println!("{msg:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
class topological
|
||||
dim dictDependencies
|
||||
dim dictReported
|
||||
dim depth
|
||||
|
||||
sub class_initialize
|
||||
set dictDependencies = createobject("Scripting.Dictionary")
|
||||
set dictReported = createobject("Scripting.Dictionary")
|
||||
depth = 0
|
||||
end sub
|
||||
|
||||
sub reset
|
||||
dictReported.removeall
|
||||
end sub
|
||||
|
||||
property let dependencies( s )
|
||||
'assuming token tab token-list newline
|
||||
dim i, j ,k
|
||||
dim aList
|
||||
dim dep
|
||||
dim a1
|
||||
aList = Split( s, vbNewLine )
|
||||
'~ remove empty lines at end
|
||||
do while aList( UBound( aList ) ) = vbnullstring
|
||||
redim preserve aList( UBound( aList ) - 1 )
|
||||
loop
|
||||
|
||||
for i = lbound( aList ) to ubound( aList )
|
||||
aList( i ) = Split( aList( i ), vbTab, 2 )
|
||||
a1 = Split( aList( i )( 1 ), " " )
|
||||
k = 0
|
||||
for j = lbound( a1) to ubound(a1)
|
||||
if a1(j) <> aList(i)(0) then
|
||||
a1(k) = a1(j)
|
||||
k = k + 1
|
||||
end if
|
||||
next
|
||||
redim preserve a1(k-1)
|
||||
aList(i)(1) = a1
|
||||
next
|
||||
for i = lbound( aList ) to ubound( aList )
|
||||
dep = aList(i)(0)
|
||||
if not dictDependencies.Exists( dep ) then
|
||||
dictDependencies.add dep, aList(i)(1)
|
||||
end if
|
||||
next
|
||||
|
||||
end property
|
||||
|
||||
sub resolve( s )
|
||||
dim i
|
||||
dim deps
|
||||
'~ wscript.echo string(depth,"!"),s
|
||||
depth = depth + 1
|
||||
if dictDependencies.Exists(s) then
|
||||
deps = dictDependencies(s)
|
||||
for i = lbound(deps) to ubound(deps)
|
||||
resolve deps(i)
|
||||
next
|
||||
end if
|
||||
if not seen(s) then
|
||||
wscript.echo s
|
||||
see s
|
||||
end if
|
||||
depth = depth - 1
|
||||
end sub
|
||||
|
||||
function seen( key )
|
||||
seen = dictReported.Exists( key )
|
||||
end function
|
||||
|
||||
sub see( key )
|
||||
dictReported.add key, ""
|
||||
end sub
|
||||
|
||||
property get keys
|
||||
keys = dictDependencies.keys
|
||||
end property
|
||||
end class
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
dim toposort
|
||||
set toposort = new topological
|
||||
toposort.dependencies = "des_system_lib std synopsys std_cell_lib des_system_lib dw02 dw01 ramlib ieee" & vbNewLine & _
|
||||
"dw01 ieee dw01 dware gtech" & vbNewLine & _
|
||||
"dw02 ieee dw02 dware" & vbNewLine & _
|
||||
"dw03 std synopsys dware dw03 dw02 dw01 ieee gtech" & vbNewLine & _
|
||||
"dw04 dw04 ieee dw01 dware gtech" & vbNewLine & _
|
||||
"dw05 dw05 ieee dware" & vbNewLine & _
|
||||
"dw06 dw06 ieee dware" & vbNewLine & _
|
||||
"dw07 ieee dware" & vbNewLine & _
|
||||
"dware ieee dware" & vbNewLine & _
|
||||
"gtech ieee gtech" & vbNewLine & _
|
||||
"ramlib std ieee" & vbNewLine & _
|
||||
"std_cell_lib ieee std_cell_lib" & vbNewLine & _
|
||||
"synopsys "
|
||||
|
||||
dim k
|
||||
for each k in toposort.keys
|
||||
wscript.echo "----- " & k
|
||||
toposort.resolve k
|
||||
wscript.echo "-----"
|
||||
toposort.reset
|
||||
next
|
||||
Loading…
Add table
Add a link
Reference in a new issue