@@ -12,6 +12,7 @@ use crate::{
1212use std:: {
1313 cell:: { Ref , RefCell , RefMut } ,
1414 collections:: { HashMap , HashSet } ,
15+ num:: ParseIntError ,
1516 rc:: { Rc , Weak } ,
1617} ;
1718
@@ -106,6 +107,7 @@ impl Gate {
106107
107108/// An operand to an [Instantiable]
108109#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
110+ #[ cfg_attr( feature = "serde" , derive( :: serde:: Serialize , :: serde:: Deserialize ) ) ]
109111enum Operand {
110112 /// An index into the list of objects
111113 DirectIndex ( usize ) ,
@@ -139,6 +141,33 @@ impl Operand {
139141 }
140142}
141143
144+ impl std:: fmt:: Display for Operand {
145+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
146+ match self {
147+ Operand :: DirectIndex ( idx) => write ! ( f, "{idx}" ) ,
148+ Operand :: CellIndex ( idx, j) => write ! ( f, "{idx}.{j}" ) ,
149+ }
150+ }
151+ }
152+
153+ impl std:: str:: FromStr for Operand {
154+ type Err = ParseIntError ;
155+
156+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
157+ match s. split_once ( '.' ) {
158+ Some ( ( idx, j) ) => {
159+ let idx = idx. parse :: < usize > ( ) ?;
160+ let j = j. parse :: < usize > ( ) ?;
161+ Ok ( Operand :: CellIndex ( idx, j) )
162+ }
163+ None => {
164+ let idx = s. parse :: < usize > ( ) ?;
165+ Ok ( Operand :: DirectIndex ( idx) )
166+ }
167+ }
168+ }
169+ }
170+
142171/// An object that has a reference to its owning netlist/module
143172#[ derive( Debug ) ]
144173struct OwnedObject < I , O >
@@ -1796,6 +1825,15 @@ where
17961825 pub fn dfs ( & self , from : NetRef < I > ) -> impl Iterator < Item = NetRef < I > > {
17971826 iter:: DFSIterator :: new ( self , from)
17981827 }
1828+
1829+ #[ cfg( feature = "serde" ) ]
1830+ /// Serializes the netlist to a writer.
1831+ pub fn serialize ( self , writer : impl std:: io:: Write ) -> Result < ( ) , serde_json:: Error >
1832+ where
1833+ I : :: serde:: Serialize ,
1834+ {
1835+ serde:: netlist_serialize ( self , writer)
1836+ }
17991837}
18001838
18011839impl < I > std:: fmt:: Display for Netlist < I >
@@ -1989,3 +2027,155 @@ fn test_delete_netlist() {
19892027pub type GateNetlist = Netlist < Gate > ;
19902028/// A type alias to Gate circuit nodes
19912029pub type GateRef = NetRef < Gate > ;
2030+
2031+ #[ cfg( feature = "serde" ) ]
2032+ /// Serde support for netlists
2033+ pub mod serde {
2034+ use super :: { Netlist , Operand , OwnedObject , WeakIndex } ;
2035+ use crate :: {
2036+ attribute:: { AttributeKey , AttributeValue } ,
2037+ circuit:: { Instantiable , Net , Object } ,
2038+ } ;
2039+ use serde:: { Deserialize , Serialize , de:: DeserializeOwned } ;
2040+ use std:: cell:: RefCell ;
2041+ use std:: { collections:: HashMap , rc:: Rc } ;
2042+
2043+ #[ derive( Debug , Serialize , Deserialize ) ]
2044+ struct SerdeObject < I >
2045+ where
2046+ I : Instantiable + Serialize ,
2047+ {
2048+ /// The object that is owned by the netlist
2049+ object : Object < I > ,
2050+ /// The list of operands for the object
2051+ operands : Vec < Option < Operand > > ,
2052+ /// A collection of attributes for the object
2053+ attributes : HashMap < AttributeKey , AttributeValue > ,
2054+ }
2055+
2056+ impl < I , O > From < OwnedObject < I , O > > for SerdeObject < I >
2057+ where
2058+ I : Instantiable + Serialize ,
2059+ O : WeakIndex < usize , Output = OwnedObject < I , O > > ,
2060+ {
2061+ fn from ( value : OwnedObject < I , O > ) -> Self {
2062+ SerdeObject {
2063+ object : value. object ,
2064+ operands : value. operands ,
2065+ attributes : value. attributes ,
2066+ }
2067+ }
2068+ }
2069+
2070+ impl < I > SerdeObject < I >
2071+ where
2072+ I : Instantiable + Serialize ,
2073+ {
2074+ fn into_owned_object < O > ( self , owner : & Rc < O > , index : usize ) -> OwnedObject < I , O >
2075+ where
2076+ O : WeakIndex < usize , Output = OwnedObject < I , O > > ,
2077+ {
2078+ OwnedObject {
2079+ object : self . object ,
2080+ owner : Rc :: downgrade ( owner) ,
2081+ operands : self . operands ,
2082+ attributes : self . attributes ,
2083+ index,
2084+ }
2085+ }
2086+ }
2087+
2088+ #[ derive( Debug , Serialize , Deserialize ) ]
2089+ struct SerdeNetlist < I >
2090+ where
2091+ I : Instantiable + Serialize ,
2092+ {
2093+ /// The name of the netlist
2094+ name : String ,
2095+ /// The list of objects in the netlist, such as inputs, modules, and primitives
2096+ objects : Vec < SerdeObject < I > > ,
2097+ /// The list of operands that point to objects which are outputs
2098+ outputs : HashMap < String , Net > ,
2099+ }
2100+
2101+ impl < I > From < Netlist < I > > for SerdeNetlist < I >
2102+ where
2103+ I : Instantiable + Serialize ,
2104+ {
2105+ fn from ( value : Netlist < I > ) -> Self {
2106+ SerdeNetlist {
2107+ name : value. name ,
2108+ objects : value
2109+ . objects
2110+ . into_inner ( )
2111+ . into_iter ( )
2112+ . map ( |o| {
2113+ Rc :: try_unwrap ( o)
2114+ . ok ( )
2115+ . expect ( "Cannot serialize with live references" )
2116+ . into_inner ( )
2117+ . into ( )
2118+ } )
2119+ . collect ( ) ,
2120+ outputs : value
2121+ . outputs
2122+ . into_inner ( )
2123+ . into_iter ( )
2124+ // TODO(matth2k): Indices must be a string. This is a workaround until de-serialize is implemented.
2125+ . map ( |( o, n) | ( o. to_string ( ) , n) )
2126+ . collect ( ) ,
2127+ }
2128+ }
2129+ }
2130+
2131+ impl < I > SerdeNetlist < I >
2132+ where
2133+ I : Instantiable + Serialize ,
2134+ {
2135+ /// Convert the serialized netlist back into a reference-counted netlist.
2136+ fn into_netlist ( self ) -> Rc < Netlist < I > > {
2137+ let netlist = Netlist :: new ( self . name ) ;
2138+ let outputs: HashMap < Operand , Net > = self
2139+ . outputs
2140+ . into_iter ( )
2141+ . map ( |( k, v) | {
2142+ let operand = k. parse :: < Operand > ( ) . expect ( "Invalid index" ) ;
2143+ ( operand, v)
2144+ } )
2145+ . collect ( ) ;
2146+ let objects = self
2147+ . objects
2148+ . into_iter ( )
2149+ . enumerate ( )
2150+ . map ( |( i, o) | {
2151+ let owned_object = o. into_owned_object ( & netlist, i) ;
2152+ Rc :: new ( RefCell :: new ( owned_object) )
2153+ } )
2154+ . collect :: < Vec < _ > > ( ) ;
2155+ {
2156+ let mut objs_mut = netlist. objects . borrow_mut ( ) ;
2157+ * objs_mut = objects;
2158+ let mut outputs_mut = netlist. outputs . borrow_mut ( ) ;
2159+ * outputs_mut = outputs;
2160+ }
2161+ netlist
2162+ }
2163+ }
2164+
2165+ /// Serialize the netlist into the writer.
2166+ pub fn netlist_serialize < I : Instantiable + Serialize > (
2167+ netlist : Netlist < I > ,
2168+ writer : impl std:: io:: Write ,
2169+ ) -> Result < ( ) , serde_json:: Error > {
2170+ let sobj: SerdeNetlist < I > = netlist. into ( ) ;
2171+ serde_json:: to_writer_pretty ( writer, & sobj)
2172+ }
2173+
2174+ /// Deserialize a netlist from the reader.
2175+ pub fn netlist_deserialize < I : Instantiable + Serialize + DeserializeOwned > (
2176+ reader : impl std:: io:: Read ,
2177+ ) -> Result < Rc < Netlist < I > > , serde_json:: Error > {
2178+ let sobj: SerdeNetlist < I > = serde_json:: from_reader ( reader) ?;
2179+ Ok ( sobj. into_netlist ( ) )
2180+ }
2181+ }
0 commit comments