1313// limitations under the License.
1414
1515import ArgumentParser
16+ import BigInt
1617import CoreFoundation
1718import Defile
1819import Foundation
1920import PythonKit
20- import BigInt
2121
2222extension Fault {
2323 struct Assemble : ParsableCommand {
2424 static let configuration = CommandConfiguration (
2525 commandName: " asm " ,
2626 abstract: " Assemble test vectors and golden outputs from JSON and Verilog files. "
2727 )
28-
28+
2929 @Option ( name: [ . customShort( " o " ) , . long] , help: " Path to the output vector file. " )
3030 var output : String ?
31-
31+
3232 @Option ( name: [ . customShort( " O " ) , . long] , help: " Path to the golden output file. " )
3333 var goldenOutput : String ?
34-
34+
3535 @Argument ( help: " JSON file (.json). " )
3636 var json : String
37-
37+
3838 @Argument ( help: " Verilog file (.v) " )
3939 var verilog : String
40-
40+
4141 mutating func run( ) throws {
4242 // Validate input files
4343 guard FileManager . default. fileExists ( atPath: verilog) else {
@@ -46,52 +46,56 @@ extension Fault {
4646 guard FileManager . default. fileExists ( atPath: json) else {
4747 throw ValidationError ( " JSON file ' \( json) ' not found. " )
4848 }
49-
49+
5050 let vectorOutput = output ?? json. replacingExtension ( " .json " , with: " .bin " )
5151 let goldenOutput = goldenOutput ?? json. replacingExtension ( " .tv.json " , with: " .au.bin " )
52-
52+
5353 print ( " Loading JSON data… " )
5454 guard let data = try ? Data ( contentsOf: URL ( fileURLWithPath: json) ) else {
5555 throw ValidationError ( " Failed to open test vector JSON file. " )
5656 }
57-
57+
5858 let decoder = JSONDecoder ( )
5959 guard let tvinfo = try ? decoder. decode ( TVInfo . self, from: data) else {
6060 throw ValidationError ( " Test vector JSON file is invalid. " )
6161 }
62-
62+
6363 // Extract chain metadata
6464 let ( chain, _, _) = ChainMetadata . extract ( file: verilog)
65-
65+
6666 let order = chain. filter { $0. kind != . output } . sorted { $0. ordinal < $1. ordinal }
6767 let outputOrder = chain. filter { $0. kind != . input } . sorted { $0. ordinal < $1. ordinal }
68-
68+
6969 let jsInputOrder = tvinfo. inputs
7070 let jsOutputOrder = tvinfo. outputs
71-
71+
7272 var inputMap : [ String : Int ] = [ : ]
7373 var outputMap : [ String : Int ] = [ : ]
74-
74+
7575 // Check input order
7676 let chainOrder = order. filter { $0. kind != . bypassInput }
7777 guard chainOrder. count == jsInputOrder. count else {
78- throw ValidationError ( " Number of inputs in the test-vector JSON file ( \( jsInputOrder. count) ) does not match scan-chain registers ( \( chainOrder. count) ): Found \( Set ( chainOrder. map { $0. name } ) . symmetricDifference ( jsInputOrder. map { $0. name } ) ) . " )
78+ throw ValidationError (
79+ " Number of inputs in the test-vector JSON file ( \( jsInputOrder. count) ) does not match scan-chain registers ( \( chainOrder. count) ): Found \( Set ( chainOrder. map ( \. name) ) . symmetricDifference ( jsInputOrder. map ( \. name) ) ) . "
80+ )
7981 }
80-
82+
8183 for (i, input) in jsInputOrder. enumerated ( ) {
8284 let name = input. name. hasPrefix ( " \\ " ) ? String ( input. name. dropFirst ( ) ) : input. name
8385 inputMap [ name] = i
8486 guard chainOrder [ i] . name == name else {
85- throw ValidationError ( " Ordinal mismatch between TV input \( name) and scan-chain register \( chainOrder [ i] . name) . " )
87+ throw ValidationError (
88+ " Ordinal mismatch between TV input \( name) and scan-chain register \( chainOrder [ i] . name) . "
89+ )
8690 }
8791 }
88-
92+
8993 for (i, output) in jsOutputOrder. enumerated ( ) {
9094 var name = output. name. hasPrefix ( " \\ " ) ? String ( output. name. dropFirst ( ) ) : output. name
9195 name = name. hasSuffix ( " .d " ) ? String ( name. dropLast ( 2 ) ) : name
9296 outputMap [ name] = i
9397 }
94-
98+
9599 var outputDecimal : [ [ BigUInt ] ] = [ ]
96100 for tvcPair in tvinfo. coverageList {
97101 guard let hex = BigUInt ( tvcPair. goldenOutput, radix: 16 ) else {
@@ -105,13 +109,13 @@ extension Fault {
105109 for output in jsOutputOrder {
106110 let start = outputBinary. index ( outputBinary. startIndex, offsetBy: pointer)
107111 let end = outputBinary. index ( start, offsetBy: output. width)
108- let value = String ( outputBinary [ start..< end] )
112+ let value = String ( outputBinary [ start ..< end] )
109113 list. append ( BigUInt ( value, radix: 2 ) !)
110114 pointer += output. width
111115 }
112116 outputDecimal. append ( list)
113117 }
114-
118+
115119 var binFileVec = " // test-vector \n "
116120 var binFileOut = " // fault-free-response \n "
117121 for (i, tvcPair) in tvinfo. coverageList. enumerated ( ) {
@@ -136,26 +140,29 @@ extension Fault {
136140 } else if element. kind == . bypassOutput {
137141 outputBinary += String ( repeating: " x " , count: element. width)
138142 } else {
139- throw ValidationError ( " Mismatch between output port \( element. name) and chained netlist. " )
143+ throw ValidationError (
144+ " Mismatch between output port \( element. name) and chained netlist. " )
140145 }
141146 }
142147 binFileVec += binaryString + " \n "
143148 binFileOut += outputBinary + " \n "
144149 }
145-
150+
146151 let vectorCount = tvinfo. coverageList. count
147152 let vectorLength = order. reduce ( 0 ) { $0 + $1. width }
148-
153+
149154 let vecMetadata = binMetadata ( count: vectorCount, length: vectorLength)
150- let outMetadata = binMetadata ( count: vectorCount, length: outputOrder. reduce ( 0 ) { $0 + $1. width } )
151-
155+ let outMetadata = binMetadata (
156+ count: vectorCount, length: outputOrder. reduce ( 0 ) { $0 + $1. width }
157+ )
158+
152159 guard let vecMetadataString = vecMetadata. toJSON ( ) else {
153160 throw ValidationError ( " Could not generate metadata string. " )
154161 }
155162 guard let outMetadataString = outMetadata. toJSON ( ) else {
156163 throw ValidationError ( " Could not generate metadata string. " )
157164 }
158-
165+
159166 try File . open ( vectorOutput, mode: . write) {
160167 try $0. print ( String . boilerplate)
161168 try $0. print ( " /* FAULT METADATA: '\(vecMetadataString)' END FAULT METADATA */" )
@@ -166,7 +173,7 @@ extension Fault {
166173 try $0. print ( " /* FAULT METADATA: '\(outMetadataString)' END FAULT METADATA */" )
167174 try $0. print ( binFileOut, terminator: " " )
168175 }
169-
176+
170177 print ( " Test vectors and golden outputs assembled successfully. " )
171178 }
172179 }
0 commit comments