Skip to content

Commit

Permalink
Add support for multiple black-boxed macros (#43)
Browse files Browse the repository at this point in the history
* Added logging to `fault jtag` simulations
* New flags
  * `--blackbox` names of modules (not instances) inside the design to be blackboxed (i.e. connections treated as outputs or inputs to the circuit): Added to `chain`, `cut`
  * `--blackboxModels`: Verilog files containing behavioral models for black-boxed instances for simulation: Added to `chain`, `jtag` and must be readable by Pyverilog (sorry)
  * `--output-fault-points`: Outputs all detected fault points: Added to `main`
  * `--output-covered`: Outputs coverage metadata: Added to `main`
* Created new element, `Module`, which captures and stores metadata about modules
* Rewrote simulation scripts to use an array of `models` instead of separate `cells` and `includes`
* Rewrote major parts of `fault chain` to support multiple macros (and general code quality)
* Fixed a bug where `fault asm` did not load some input names correctly

## Testing
* Added new design, `TripleDelay`, to test the use of macros
  • Loading branch information
donn authored Jan 15, 2024
1 parent 6a45e7c commit 90b1192
Show file tree
Hide file tree
Showing 32 changed files with 1,442 additions and 1,358 deletions.
34 changes: 0 additions & 34 deletions .github/workflows/appimage.yml

This file was deleted.

3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ jobs:
- name: Build Image
run: |
docker build --target runner -t aucohl/fault:latest .
- name: Run Smoke Test
run: |
docker run --rm -w /test aucohl/fault:latest python3 /test/smoke_test.py
- name: Check for new version
if: ${{ env.BRANCH_NAME == 'main' }}
run: |
Expand Down
14 changes: 11 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ WORKDIR /
COPY requirements.txt /requirements.txt
RUN python3 -m pip install --target /build/lib/pythonpath --upgrade -r ./requirements.txt

# Copy Libraries for AppImage
RUN cp /lib64/libtinfo.so.5 /build/lib
RUN cp /lib64/libffi.so.6 /build/lib
RUN cp /lib64/libz.so.1 /build/lib
Expand All @@ -74,14 +73,23 @@ ENV CC=clang
ENV CXX=clang++
RUN swift build --static-swift-stdlib -c release
RUN cp /fault/.build/x86_64-unknown-linux-gnu/release/Fault /build/bin/fault

## Tests
ENV PATH=/build/bin:$PATH\
PYTHON_LIBRARY=/build/lib/libpython3.6m.so\
PYTHONPATH=/build/lib/pythonpath\
LD_LIBRARY_PATH=/build/lib\
FAULT_IVL_BASE=/build/lib/ivl\
FAULT_IVERILOG=/build/bin/iverilog\
FAULT_VVP=/build/bin/vvp
RUN swift test

WORKDIR /
# ---

FROM centos:centos7 AS runner
COPY --from=builder /build /build
WORKDIR /test
COPY ./Tests/smoke_test.py .
COPY ./Tests/RTL/spm.v .
COPY ./Tech/osu035 ./osu035

WORKDIR /
Expand Down
15 changes: 1 addition & 14 deletions OSAcknowledgements
Original file line number Diff line number Diff line change
Expand Up @@ -202,19 +202,6 @@ Pyverilog, Tensorflow for Swift/PythonKit, CommandLineKit, OpenLane
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---
Magic (AppImage Build Files)

Copyright (C) 2022 R. Timothy Edwards

Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies. The University of California
makes no representations about the suitability of this
software for any purpose. It is provided "as is" without
express or implied warranty. Export of this software outside
of the United States of America may require an export license.

---
Python Lex-Yacc
Expand All @@ -226,4 +213,4 @@ Redistribution and use in source and binary forms, with or without modification,
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the David Beazley or Dabeaz LLC may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 change: 0 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/apple/swift-collections.git", .upToNextMajor(from: "1.0.0")),
.package(url: "https://github.com/pvieito/PythonKit", .branch("master")),
.package(url: "https://github.com/pvieito/CommandLineKit", .branch("master")),
Expand Down
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 🧪 Fault
![Swift 5.4+](https://img.shields.io/badge/Swift-5.4-orange?logo=swift) ![Docker Image Available for x86-64](https://img.shields.io/static/v1?logo=docker&label=docker&message=x86_64) ![AppImage Available for Linux x86-64](https://img.shields.io/static/v1?label=appimage&message=x86_64&color=blue)
![Swift 5.4+](https://img.shields.io/badge/Swift-5.4-orange?logo=swift) ![Docker Image Available for x86-64](https://img.shields.io/static/v1?logo=docker&label=docker&message=x86_64)

Fault is a complete open source design for testing (DFT) Solution that includes automatic test pattern generation for netlists, scan chain stitching, synthesis scripts and a number of other convenience features.

Expand Down
20 changes: 8 additions & 12 deletions Sources/Fault/BoundaryScanRegister.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,21 @@ class BoundaryScanRegisterCreator {
}

func create(
ordinal: Int,
max: Int,
din: String,
dout: String,
group: String,
din: PythonObject,
dout: PythonObject,
sin: String,
sout: String,
input: Bool
) -> PythonObject {
let dinIdentifier = Node.Identifier(din)
let doutIdentifier = Node.Identifier(dout)
let sinIdentifier = Node.Identifier(sin)
let soutIdentifier = Node.Identifier(sout)
let ordinalConstant = Node.Constant(ordinal)

let name = input ? inputName : outputName
let dinArg = (max == 0) ? dinIdentifier : Node.Pointer(dinIdentifier, ordinalConstant)
let doutArg = (max == 0) ? doutIdentifier : Node.Pointer(doutIdentifier, ordinalConstant)

let portArguments = [
Node.PortArg("din", dinArg),
Node.PortArg("dout", doutArg),
Node.PortArg("din", din),
Node.PortArg("dout", dout),
Node.PortArg("sin", sinIdentifier),
Node.PortArg("sout", soutIdentifier),
Node.PortArg("clock", clockIdentifier),
Expand All @@ -94,9 +88,11 @@ class BoundaryScanRegisterCreator {
Node.PortArg("shift", shiftIdentifier),
]

let instanceName = "__\(name)_\(group)_\(counter)__"

let submoduleInstance = Node.Instance(
name,
"__" + name + "_" + String(describing: counter) + "__",
instanceName,
Python.tuple(portArguments),
Python.tuple()
)
Expand Down
40 changes: 17 additions & 23 deletions Sources/Fault/Entries/asm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import BigInt
import CommandLineKit
import Defile
import Foundation
import PythonKit

func assemble(arguments: [String]) -> Int32 {
let cli = CommandLineKit.CommandLine(arguments: arguments)
Expand Down Expand Up @@ -75,16 +74,22 @@ func assemble(arguments: [String]) -> Int32 {
let vectorOutput = filePath.value ?? "\(json).vec.bin"
let goldenOutput = goldenFilePath.value ?? "\(json).out.bin"

guard let jsonString = File.read(json) else {
Stderr.print("Could not read file '\(json)'")
return EX_NOINPUT
print("Loading JSON data…")
let start = DispatchTime.now()
guard let data = try? Data(contentsOf: URL(fileURLWithPath: json)) else {
Stderr.print("Failed to open test vector JSON file.")
return EX_DATAERR
}

let decoder = JSONDecoder()
guard let tvinfo = try? decoder.decode(TVInfo.self, from: jsonString.data(using: .utf8)!) else {
guard let tvinfo = try? decoder.decode(TVInfo.self, from: data) else {
Stderr.print("Test vector json file is invalid.")
return EX_DATAERR
}
let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime) / 1_000_000_000
print("Loaded JSON data in \(timeInterval)s.")

let (chain, _, _) = ChainMetadata.extract(file: netlist)

Expand All @@ -110,9 +115,10 @@ func assemble(arguments: [String]) -> Int32 {
}

for (i, input) in jsInputOrder.enumerated() {
inputMap[input.name] = i
if chainOrder[i].name != input.name {
print("[Error]: Ordinal mismatch between TV input \(input.name) and scan-chain register \(chainOrder[i].name).")
let name = (input.name.hasPrefix("\\")) ? String(input.name.dropFirst(1)) : input.name
inputMap[name] = i
if chainOrder[i].name != name {
print("[Error]: Ordinal mismatch between TV input \(name) and scan-chain register \(chainOrder[i].name).")
return EX_DATAERR
}
}
Expand All @@ -123,17 +129,6 @@ func assemble(arguments: [String]) -> Int32 {
outputMap[name] = i
}

func pad(_ number: BigUInt, digits: Int, radix: Int) -> String {
var padded = String(number, radix: radix)
let length = padded.count
if digits > length {
for _ in 0 ..< (digits - length) {
padded = "0" + padded
}
}
return padded
}

var jsOutputLength = 0
for output in jsOutputOrder {
jsOutputLength += output.width
Expand Down Expand Up @@ -181,20 +176,19 @@ func assemble(arguments: [String]) -> Int32 {
return EX_DATAERR
}
}
binaryString += pad(value, digits: element.width, radix: 2).reversed()
binaryString += value.pad(digits: element.width, radix: 2).reversed()
}
var outputBinary = ""
for element in orderOutput {
var value: BigUInt = 0
if let locus = outputMap[element.name] {
value = outputDecimal[i][locus]
outputBinary += pad(value, digits: element.width, radix: 2)
outputBinary += value.pad(digits: element.width, radix: 2)
} else {
if element.kind == .bypassOutput {
outputBinary += String(repeating: "x", count: element.width)
print("Output is same as the loaded TV")
} else {
print("[Error]: Mismatch between output port \(element.name) and chained netlist. ")
print("[Error]: Mismatch between output port \(element.name) and chained netlist.")
return EX_DATAERR
}
}
Expand Down
Loading

0 comments on commit 90b1192

Please sign in to comment.