for release 0.0.4
- Circuit: is now pickleable and comparable - Circuit: utilities for locating/indexing io-ports - Verilog: parser fixes, support yosys-style verilog - SDF: parser fixes, full XOR support - STIL: parser fixes - Simulators: faster, up to 4-input cells, pickleable - WaveSim: WSA calculation support - WaveSim: Per-simulation parameters and delays - Logic: Data are now raw numpy arrays - Logic: More tools for bit-packing - Added DEF parser - Better techlib support for NanGate, SAED, GSC180 - Tests and docs improvements
This commit is contained in:
1 parent
840b816804
commit
351d809306
49 files changed
+7173
-3870
No files matched your search
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+13
-1
@@ -1,8 +1,20 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@pytest.fixture(scope='session')
|
||||
def mydir():
|
||||
import os
|
||||
from pathlib import Path
|
||||
return Path(os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))))
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def b15_2ig_circuit(mydir):
|
||||
from kyupy import verilog
|
||||
from kyupy.techlib import SAED32
|
||||
return verilog.load(mydir / 'b15_2ig.v.gz', branchforks=True, tlib=SAED32)
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def b15_2ig_delays(mydir, b15_2ig_circuit):
|
||||
from kyupy import sdf
|
||||
from kyupy.techlib import SAED32
|
||||
return sdf.load(mydir / 'b15_2ig.sdf.gz').iopaths(b15_2ig_circuit, tlib=SAED32)[1:2]
|
||||
@@ -0,0 +1,335 @@
|
||||
/* Generated by Yosys 0.9 (git sha1 UNKNOWN, gcc 4.8.5 -fPIC -Os) */
|
||||
|
||||
(* top = 1 *)
|
||||
(* src = "rng_haltonBase2.v:1" *)
|
||||
module rng1(clk, reset, o_output);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
wire [11:0] _00_;
|
||||
wire _01_;
|
||||
wire _02_;
|
||||
wire _03_;
|
||||
wire _04_;
|
||||
wire _05_;
|
||||
wire _06_;
|
||||
wire _07_;
|
||||
wire _08_;
|
||||
wire _09_;
|
||||
wire _10_;
|
||||
wire _11_;
|
||||
wire _12_;
|
||||
wire _13_;
|
||||
wire _14_;
|
||||
wire _15_;
|
||||
wire _16_;
|
||||
wire _17_;
|
||||
wire _18_;
|
||||
wire _19_;
|
||||
wire _20_;
|
||||
wire _21_;
|
||||
wire _22_;
|
||||
wire _23_;
|
||||
wire _24_;
|
||||
wire _25_;
|
||||
wire _26_;
|
||||
wire _27_;
|
||||
wire _28_;
|
||||
wire _29_;
|
||||
wire _30_;
|
||||
wire _31_;
|
||||
wire _32_;
|
||||
wire _33_;
|
||||
wire _34_;
|
||||
(* src = "rng_haltonBase2.v:2" *)
|
||||
input clk;
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:12" *)
|
||||
wire \halton.clk ;
|
||||
(* init = 12'h000 *)
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:17" *)
|
||||
wire [11:0] \halton.counter ;
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:14" *)
|
||||
wire [11:0] \halton.o_output ;
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:13" *)
|
||||
wire \halton.reset ;
|
||||
(* src = "rng_haltonBase2.v:4" *)
|
||||
output [11:0] o_output;
|
||||
(* src = "rng_haltonBase2.v:3" *)
|
||||
input reset;
|
||||
AND2X1 _35_ (
|
||||
.IN1(\halton.counter [1]),
|
||||
.IN2(\halton.counter [0]),
|
||||
.Q(_01_)
|
||||
);
|
||||
NOR2X0 _36_ (
|
||||
.IN1(\halton.counter [1]),
|
||||
.IN2(\halton.counter [0]),
|
||||
.QN(_02_)
|
||||
);
|
||||
NOR3X0 _37_ (
|
||||
.IN1(reset),
|
||||
.IN2(_01_),
|
||||
.IN3(_02_),
|
||||
.QN(_00_[1])
|
||||
);
|
||||
AND2X1 _38_ (
|
||||
.IN1(\halton.counter [2]),
|
||||
.IN2(_01_),
|
||||
.Q(_03_)
|
||||
);
|
||||
NOR2X0 _39_ (
|
||||
.IN1(\halton.counter [2]),
|
||||
.IN2(_01_),
|
||||
.QN(_04_)
|
||||
);
|
||||
NOR3X0 _40_ (
|
||||
.IN1(reset),
|
||||
.IN2(_03_),
|
||||
.IN3(_04_),
|
||||
.QN(_00_[2])
|
||||
);
|
||||
AND4X1 _41_ (
|
||||
.IN1(\halton.counter [1]),
|
||||
.IN2(\halton.counter [0]),
|
||||
.IN3(\halton.counter [2]),
|
||||
.IN4(\halton.counter [3]),
|
||||
.Q(_05_)
|
||||
);
|
||||
NOR2X0 _42_ (
|
||||
.IN1(\halton.counter [3]),
|
||||
.IN2(_03_),
|
||||
.QN(_06_)
|
||||
);
|
||||
NOR3X0 _43_ (
|
||||
.IN1(reset),
|
||||
.IN2(_05_),
|
||||
.IN3(_06_),
|
||||
.QN(_00_[3])
|
||||
);
|
||||
AND2X1 _44_ (
|
||||
.IN1(\halton.counter [4]),
|
||||
.IN2(_05_),
|
||||
.Q(_07_)
|
||||
);
|
||||
NOR2X0 _45_ (
|
||||
.IN1(\halton.counter [4]),
|
||||
.IN2(_05_),
|
||||
.QN(_08_)
|
||||
);
|
||||
NOR3X0 _46_ (
|
||||
.IN1(reset),
|
||||
.IN2(_07_),
|
||||
.IN3(_08_),
|
||||
.QN(_00_[4])
|
||||
);
|
||||
AND2X1 _47_ (
|
||||
.IN1(\halton.counter [5]),
|
||||
.IN2(_07_),
|
||||
.Q(_09_)
|
||||
);
|
||||
NOR2X0 _48_ (
|
||||
.IN1(\halton.counter [5]),
|
||||
.IN2(_07_),
|
||||
.QN(_10_)
|
||||
);
|
||||
NOR3X0 _49_ (
|
||||
.IN1(reset),
|
||||
.IN2(_09_),
|
||||
.IN3(_10_),
|
||||
.QN(_00_[5])
|
||||
);
|
||||
AND4X1 _50_ (
|
||||
.IN1(\halton.counter [4]),
|
||||
.IN2(\halton.counter [5]),
|
||||
.IN3(\halton.counter [6]),
|
||||
.IN4(_05_),
|
||||
.Q(_11_)
|
||||
);
|
||||
NOR2X0 _51_ (
|
||||
.IN1(\halton.counter [6]),
|
||||
.IN2(_09_),
|
||||
.QN(_12_)
|
||||
);
|
||||
NOR3X0 _52_ (
|
||||
.IN1(reset),
|
||||
.IN2(_11_),
|
||||
.IN3(_12_),
|
||||
.QN(_00_[6])
|
||||
);
|
||||
AND2X1 _53_ (
|
||||
.IN1(\halton.counter [7]),
|
||||
.IN2(_11_),
|
||||
.Q(_13_)
|
||||
);
|
||||
NOR2X0 _54_ (
|
||||
.IN1(\halton.counter [7]),
|
||||
.IN2(_11_),
|
||||
.QN(_14_)
|
||||
);
|
||||
NOR3X0 _55_ (
|
||||
.IN1(reset),
|
||||
.IN2(_13_),
|
||||
.IN3(_14_),
|
||||
.QN(_00_[7])
|
||||
);
|
||||
AND3X1 _56_ (
|
||||
.IN1(\halton.counter [7]),
|
||||
.IN2(\halton.counter [8]),
|
||||
.IN3(_11_),
|
||||
.Q(_15_)
|
||||
);
|
||||
NOR2X0 _57_ (
|
||||
.IN1(\halton.counter [8]),
|
||||
.IN2(_13_),
|
||||
.QN(_16_)
|
||||
);
|
||||
NOR3X0 _58_ (
|
||||
.IN1(reset),
|
||||
.IN2(_15_),
|
||||
.IN3(_16_),
|
||||
.QN(_00_[8])
|
||||
);
|
||||
AND4X1 _59_ (
|
||||
.IN1(\halton.counter [7]),
|
||||
.IN2(\halton.counter [8]),
|
||||
.IN3(\halton.counter [9]),
|
||||
.IN4(_11_),
|
||||
.Q(_17_)
|
||||
);
|
||||
NOR2X0 _60_ (
|
||||
.IN1(\halton.counter [9]),
|
||||
.IN2(_15_),
|
||||
.QN(_18_)
|
||||
);
|
||||
NOR3X0 _61_ (
|
||||
.IN1(reset),
|
||||
.IN2(_17_),
|
||||
.IN3(_18_),
|
||||
.QN(_00_[9])
|
||||
);
|
||||
AND2X1 _62_ (
|
||||
.IN1(\halton.counter [10]),
|
||||
.IN2(_17_),
|
||||
.Q(_19_)
|
||||
);
|
||||
NOR2X0 _63_ (
|
||||
.IN1(\halton.counter [10]),
|
||||
.IN2(_17_),
|
||||
.QN(_20_)
|
||||
);
|
||||
NOR3X0 _64_ (
|
||||
.IN1(reset),
|
||||
.IN2(_19_),
|
||||
.IN3(_20_),
|
||||
.QN(_00_[10])
|
||||
);
|
||||
AND3X1 _65_ (
|
||||
.IN1(\halton.counter [10]),
|
||||
.IN2(\halton.counter [11]),
|
||||
.IN3(_17_),
|
||||
.Q(_21_)
|
||||
);
|
||||
AOI21X1 _66_ (
|
||||
.IN1(\halton.counter [10]),
|
||||
.IN2(_17_),
|
||||
.IN3(\halton.counter [11]),
|
||||
.QN(_22_)
|
||||
);
|
||||
NOR3X0 _67_ (
|
||||
.IN1(reset),
|
||||
.IN2(_21_),
|
||||
.IN3(_22_),
|
||||
.QN(_00_[11])
|
||||
);
|
||||
NOR2X0 _68_ (
|
||||
.IN1(reset),
|
||||
.IN2(\halton.counter [0]),
|
||||
.QN(_00_[0])
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _69_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[0]),
|
||||
.Q(\halton.counter [0]),
|
||||
.QN(_23_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _70_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[1]),
|
||||
.Q(\halton.counter [1]),
|
||||
.QN(_24_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _71_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[2]),
|
||||
.Q(\halton.counter [2]),
|
||||
.QN(_25_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _72_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[3]),
|
||||
.Q(\halton.counter [3]),
|
||||
.QN(_26_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _73_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[4]),
|
||||
.Q(\halton.counter [4]),
|
||||
.QN(_27_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _74_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[5]),
|
||||
.Q(\halton.counter [5]),
|
||||
.QN(_28_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _75_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[6]),
|
||||
.Q(\halton.counter [6]),
|
||||
.QN(_29_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _76_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[7]),
|
||||
.Q(\halton.counter [7]),
|
||||
.QN(_30_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _77_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[8]),
|
||||
.Q(\halton.counter [8]),
|
||||
.QN(_31_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _78_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[9]),
|
||||
.Q(\halton.counter [9]),
|
||||
.QN(_32_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _79_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[10]),
|
||||
.Q(\halton.counter [10]),
|
||||
.QN(_33_)
|
||||
);
|
||||
(* src = "rng_haltonBase2.v:7|rng_haltonBase2.v:19" *)
|
||||
DFFX1 _80_ (
|
||||
.CLK(clk),
|
||||
.D(_00_[11]),
|
||||
.Q(\halton.counter [11]),
|
||||
.QN(_34_)
|
||||
);
|
||||
assign \halton.clk = clk;
|
||||
assign \halton.o_output = { \halton.counter [0], \halton.counter [1], \halton.counter [2], \halton.counter [3], \halton.counter [4], \halton.counter [5], \halton.counter [6], \halton.counter [7], \halton.counter [8], \halton.counter [9], \halton.counter [10], \halton.counter [11] };
|
||||
assign \halton.reset = reset;
|
||||
assign o_output = { \halton.counter [0], \halton.counter [1], \halton.counter [2], \halton.counter [3], \halton.counter [4], \halton.counter [5], \halton.counter [6], \halton.counter [7], \halton.counter [8], \halton.counter [9], \halton.counter [10], \halton.counter [11] };
|
||||
endmodule
|
||||
+1
-1
@@ -12,4 +12,4 @@ def test_b01(mydir):
|
||||
def test_simple():
|
||||
c = bench.parse('input(a, b) output(z) z=and(a,b)')
|
||||
assert len(c.nodes) == 4
|
||||
assert len(c.interface) == 3
|
||||
assert len(c.io_nodes) == 3
|
||||
+27
-6
@@ -1,7 +1,8 @@
|
||||
import pickle
|
||||
|
||||
from kyupy.circuit import Circuit, Node, Line
|
||||
from kyupy import verilog
|
||||
from kyupy import verilog, bench
|
||||
from kyupy.techlib import SAED32
|
||||
|
||||
def test_lines():
|
||||
c = Circuit()
|
||||
@@ -43,7 +44,7 @@ def test_lines():
|
||||
assert c.lines[0].index == 0
|
||||
assert c.lines[1].index == 1
|
||||
|
||||
assert n1.outs[2] is None
|
||||
assert len(n1.outs) == 2
|
||||
assert n2.ins[1] is None
|
||||
assert n2.ins[2] == line2
|
||||
|
||||
@@ -57,9 +58,9 @@ def test_circuit():
|
||||
assert 'in1' in c.cells
|
||||
assert 'and1' not in c.cells
|
||||
|
||||
c.interface[0] = in1
|
||||
c.interface[1] = in2
|
||||
c.interface[2] = out1
|
||||
c.io_nodes[0] = in1
|
||||
c.io_nodes[1] = in2
|
||||
c.io_nodes[2] = out1
|
||||
|
||||
and1 = Node(c, 'and1', kind='and')
|
||||
Line(c, in1, and1)
|
||||
@@ -104,9 +105,29 @@ def test_circuit():
|
||||
|
||||
|
||||
def test_pickle(mydir):
|
||||
c = verilog.load(mydir / 'b14.v.gz')
|
||||
c = verilog.load(mydir / 'b15_4ig.v.gz', tlib=SAED32)
|
||||
assert c is not None
|
||||
cs = pickle.dumps(c)
|
||||
assert cs is not None
|
||||
c2 = pickle.loads(cs)
|
||||
assert c == c2
|
||||
|
||||
|
||||
def test_substitute():
|
||||
c = bench.parse('input(i1, i2, i3, i4, i5) output(o1) aoi=AOI221(i1, i2, i3, i4, i5) o1=not(aoi)')
|
||||
assert len(c.cells) == 2
|
||||
assert len(c.io_nodes) == 6
|
||||
aoi221_impl = bench.parse('input(in1, in2, in3, in4, in5) output(q) a1=and(in1, in2) a2=and(in3, in4) q=or(a1, a2, in5)')
|
||||
assert len(aoi221_impl.cells) == 3
|
||||
assert len(aoi221_impl.io_nodes) == 6
|
||||
c.substitute(c.cells['aoi'], aoi221_impl)
|
||||
assert len(c.cells) == 4
|
||||
assert len(c.io_nodes) == 6
|
||||
|
||||
|
||||
def test_resolve(mydir):
|
||||
c = verilog.load(mydir / 'b15_4ig.v.gz', tlib=SAED32)
|
||||
s_names = [n.name for n in c.s_nodes]
|
||||
c.resolve_tlib_cells(SAED32)
|
||||
s_names_prim = [n.name for n in c.s_nodes]
|
||||
assert s_names == s_names_prim, 'resolve_tlib_cells does not preserve names or order of s_nodes'
|
||||
+51
-228
@@ -1,252 +1,75 @@
|
||||
import numpy as np
|
||||
import kyupy.logic as lg
|
||||
from kyupy.logic import mvarray, bparray, bp_to_mv, mv_to_bp
|
||||
|
||||
|
||||
def test_mvarray():
|
||||
|
||||
# instantiation with shape
|
||||
|
||||
ary = lg.MVArray(4)
|
||||
assert ary.length == 1
|
||||
assert len(ary) == 1
|
||||
assert ary.width == 4
|
||||
|
||||
ary = lg.MVArray((3, 2))
|
||||
assert ary.length == 2
|
||||
assert len(ary) == 2
|
||||
assert ary.width == 3
|
||||
|
||||
# instantiation with single vector
|
||||
|
||||
ary = lg.MVArray([1, 0, 1])
|
||||
assert ary.length == 1
|
||||
assert ary.width == 3
|
||||
assert str(ary) == "['101']"
|
||||
assert ary[0] == '101'
|
||||
|
||||
ary = lg.MVArray("10X-")
|
||||
assert ary.length == 1
|
||||
assert ary.width == 4
|
||||
assert str(ary) == "['10X-']"
|
||||
assert ary[0] == '10X-'
|
||||
|
||||
ary = lg.MVArray("1")
|
||||
assert ary.length == 1
|
||||
assert ary.width == 1
|
||||
|
||||
ary = lg.MVArray(["1"])
|
||||
assert ary.length == 1
|
||||
assert ary.width == 1
|
||||
|
||||
# instantiation with multiple vectors
|
||||
|
||||
ary = lg.MVArray([[0, 0], [0, 1], [1, 0], [1, 1]])
|
||||
assert ary.length == 4
|
||||
assert ary.width == 2
|
||||
|
||||
ary = lg.MVArray(["000", "001", "110", "---"])
|
||||
assert ary.length == 4
|
||||
assert ary.width == 3
|
||||
assert str(ary) == "['000', '001', '110', '---']"
|
||||
assert ary[2] == '110'
|
||||
|
||||
# casting to 2-valued logic
|
||||
|
||||
ary = lg.MVArray([0, 1, 2, None], m=2)
|
||||
assert ary.data[0] == lg.ZERO
|
||||
assert ary.data[1] == lg.ONE
|
||||
assert ary.data[2] == lg.ZERO
|
||||
assert ary.data[3] == lg.ZERO
|
||||
|
||||
ary = lg.MVArray("0-X1PRFN", m=2)
|
||||
assert ary.data[0] == lg.ZERO
|
||||
assert ary.data[1] == lg.ZERO
|
||||
assert ary.data[2] == lg.ZERO
|
||||
assert ary.data[3] == lg.ONE
|
||||
assert ary.data[4] == lg.ZERO
|
||||
assert ary.data[5] == lg.ONE
|
||||
assert ary.data[6] == lg.ZERO
|
||||
assert ary.data[7] == lg.ONE
|
||||
|
||||
# casting to 4-valued logic
|
||||
|
||||
ary = lg.MVArray([0, 1, 2, None, 'F'], m=4)
|
||||
assert ary.data[0] == lg.ZERO
|
||||
assert ary.data[1] == lg.ONE
|
||||
assert ary.data[2] == lg.UNKNOWN
|
||||
assert ary.data[3] == lg.UNASSIGNED
|
||||
assert ary.data[4] == lg.ZERO
|
||||
|
||||
ary = lg.MVArray("0-X1PRFN", m=4)
|
||||
assert ary.data[0] == lg.ZERO
|
||||
assert ary.data[1] == lg.UNASSIGNED
|
||||
assert ary.data[2] == lg.UNKNOWN
|
||||
assert ary.data[3] == lg.ONE
|
||||
assert ary.data[4] == lg.ZERO
|
||||
assert ary.data[5] == lg.ONE
|
||||
assert ary.data[6] == lg.ZERO
|
||||
assert ary.data[7] == lg.ONE
|
||||
|
||||
# casting to 8-valued logic
|
||||
|
||||
ary = lg.MVArray([0, 1, 2, None, 'F'], m=8)
|
||||
assert ary.data[0] == lg.ZERO
|
||||
assert ary.data[1] == lg.ONE
|
||||
assert ary.data[2] == lg.UNKNOWN
|
||||
assert ary.data[3] == lg.UNASSIGNED
|
||||
assert ary.data[4] == lg.FALL
|
||||
|
||||
ary = lg.MVArray("0-X1PRFN", m=8)
|
||||
assert ary.data[0] == lg.ZERO
|
||||
assert ary.data[1] == lg.UNASSIGNED
|
||||
assert ary.data[2] == lg.UNKNOWN
|
||||
assert ary.data[3] == lg.ONE
|
||||
assert ary.data[4] == lg.PPULSE
|
||||
assert ary.data[5] == lg.RISE
|
||||
assert ary.data[6] == lg.FALL
|
||||
assert ary.data[7] == lg.NPULSE
|
||||
|
||||
# copy constructor and casting
|
||||
|
||||
ary8 = lg.MVArray(ary, m=8)
|
||||
assert ary8.length == 1
|
||||
assert ary8.width == 8
|
||||
assert ary8.data[7] == lg.NPULSE
|
||||
|
||||
ary4 = lg.MVArray(ary, m=4)
|
||||
assert ary4.data[1] == lg.UNASSIGNED
|
||||
assert ary4.data[7] == lg.ONE
|
||||
|
||||
ary2 = lg.MVArray(ary, m=2)
|
||||
assert ary2.data[1] == lg.ZERO
|
||||
assert ary2.data[7] == lg.ONE
|
||||
def assert_equal_shape_and_contents(actual, desired):
|
||||
desired = np.array(desired, dtype=np.uint8)
|
||||
assert actual.shape == desired.shape
|
||||
np.testing.assert_allclose(actual, desired)
|
||||
|
||||
|
||||
def test_mv_operations():
|
||||
x1_2v = lg.MVArray("0011", m=2)
|
||||
x2_2v = lg.MVArray("0101", m=2)
|
||||
x1_4v = lg.MVArray("0000XXXX----1111", m=4)
|
||||
x2_4v = lg.MVArray("0X-10X-10X-10X-1", m=4)
|
||||
x1_8v = lg.MVArray("00000000XXXXXXXX--------11111111PPPPPPPPRRRRRRRRFFFFFFFFNNNNNNNN", m=8)
|
||||
x2_8v = lg.MVArray("0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN", m=8)
|
||||
def test_mvarray_single_vector():
|
||||
assert_equal_shape_and_contents(mvarray(1, 0, 1), [lg.ONE, lg.ZERO, lg.ONE])
|
||||
assert_equal_shape_and_contents(mvarray([1, 0, 1]), [lg.ONE, lg.ZERO, lg.ONE])
|
||||
assert_equal_shape_and_contents(mvarray('10X-RFPN'), [lg.ONE, lg.ZERO, lg.UNKNOWN, lg.UNASSIGNED, lg.RISE, lg.FALL, lg.PPULSE, lg.NPULSE])
|
||||
assert_equal_shape_and_contents(mvarray(['1']), [lg.ONE])
|
||||
assert_equal_shape_and_contents(mvarray('1'), [lg.ONE])
|
||||
|
||||
assert lg.mv_not(x1_2v)[0] == '1100'
|
||||
assert lg.mv_not(x1_4v)[0] == '1111XXXXXXXX0000'
|
||||
assert lg.mv_not(x1_8v)[0] == '11111111XXXXXXXXXXXXXXXX00000000NNNNNNNNFFFFFFFFRRRRRRRRPPPPPPPP'
|
||||
|
||||
assert lg.mv_or(x1_2v, x2_2v)[0] == '0111'
|
||||
assert lg.mv_or(x1_4v, x2_4v)[0] == '0XX1XXX1XXX11111'
|
||||
assert lg.mv_or(x1_8v, x2_8v)[0] == '0XX1PRFNXXX1XXXXXXX1XXXX11111111PXX1PRFNRXX1RRNNFXX1FNFNNXX1NNNN'
|
||||
def test_mvarray_multi_vector():
|
||||
assert_equal_shape_and_contents(mvarray([0, 0], [0, 1], [1, 0], [1, 1]), [[lg.ZERO, lg.ZERO, lg.ONE, lg.ONE], [lg.ZERO, lg.ONE, lg.ZERO, lg.ONE]])
|
||||
assert_equal_shape_and_contents(mvarray('10X', '--1'), [[lg.ONE, lg.UNASSIGNED], [lg.ZERO, lg.UNASSIGNED], [lg.UNKNOWN, lg.ONE]])
|
||||
|
||||
assert lg.mv_and(x1_2v, x2_2v)[0] == '0001'
|
||||
assert lg.mv_and(x1_4v, x2_4v)[0] == '00000XXX0XXX0XX1'
|
||||
assert lg.mv_and(x1_8v, x2_8v)[0] == '000000000XXXXXXX0XXXXXXX0XX1PRFN0XXPPPPP0XXRPRPR0XXFPPFF0XXNPRFN'
|
||||
|
||||
assert lg.mv_xor(x1_2v, x2_2v)[0] == '0110'
|
||||
assert lg.mv_xor(x1_4v, x2_4v)[0] == '0XX1XXXXXXXX1XX0'
|
||||
assert lg.mv_xor(x1_8v, x2_8v)[0] == '0XX1PRFNXXXXXXXXXXXXXXXX1XX0NFRPPXXNPRFNRXXFRPNFFXXRFNPRNXXPNFRP'
|
||||
def test_mv_ops():
|
||||
x1_8v = mvarray('00000000XXXXXXXX--------11111111PPPPPPPPRRRRRRRRFFFFFFFFNNNNNNNN')
|
||||
x2_8v = mvarray('0X-1PRFN'*8)
|
||||
|
||||
x30_2v = lg.MVArray("0000", m=2)
|
||||
x31_2v = lg.MVArray("1111", m=2)
|
||||
x30_4v = lg.MVArray("0000000000000000", m=4)
|
||||
x31_4v = lg.MVArray("1111111111111111", m=4)
|
||||
x30_8v = lg.MVArray("0000000000000000000000000000000000000000000000000000000000000000", m=8)
|
||||
x31_8v = lg.MVArray("1111111111111111111111111111111111111111111111111111111111111111", m=8)
|
||||
assert_equal_shape_and_contents(lg.mv_not(x1_8v), mvarray('11111111XXXXXXXXXXXXXXXX00000000NNNNNNNNFFFFFFFFRRRRRRRRPPPPPPPP'))
|
||||
assert_equal_shape_and_contents(lg.mv_or(x1_8v, x2_8v), mvarray('0XX1PRFNXXX1XXXXXXX1XXXX11111111PXX1PRFNRXX1RRNNFXX1FNFNNXX1NNNN'))
|
||||
assert_equal_shape_and_contents(lg.mv_and(x1_8v, x2_8v), mvarray('000000000XXXXXXX0XXXXXXX0XX1PRFN0XXPPPPP0XXRPRPR0XXFPPFF0XXNPRFN'))
|
||||
assert_equal_shape_and_contents(lg.mv_xor(x1_8v, x2_8v), mvarray('0XX1PRFNXXXXXXXXXXXXXXXX1XX0NFRPPXXNPRFNRXXFRPNFFXXRFNPRNXXPNFRP'))
|
||||
|
||||
assert lg.mv_latch(x1_2v, x2_2v, x30_2v)[0] == '0001'
|
||||
assert lg.mv_latch(x1_2v, x2_2v, x31_2v)[0] == '1011'
|
||||
assert lg.mv_latch(x1_4v, x2_4v, x30_4v)[0] == '0XX00XXX0XXX0XX1'
|
||||
assert lg.mv_latch(x1_4v, x2_4v, x31_4v)[0] == '1XX01XXX1XXX1XX1'
|
||||
assert lg.mv_latch(x1_8v, x2_8v, x30_8v)[0] == '0XX000000XXXXXXX0XXXXXXX0XX10R110XX000000XXR0R0R0XXF001F0XX10R11'
|
||||
assert lg.mv_latch(x1_8v, x2_8v, x31_8v)[0] == '1XX01F001XXXXXXX1XXXXXXX1XX111111XX01F001XXR110R1XXF1F1F1XX11111'
|
||||
# TODO
|
||||
#assert_equal_shape_and_contents(lg.mv_transition(x1_8v, x2_8v), mvarray('0XXR PRFNXXXXXXXXXXXXXXXX1XX0NFRPPXXNPRFNRXXFRPNFFXXRFNPRNXXPNFRP'))
|
||||
|
||||
x30_8v = mvarray('0000000000000000000000000000000000000000000000000000000000000000')
|
||||
x31_8v = mvarray('1111111111111111111111111111111111111111111111111111111111111111')
|
||||
|
||||
assert_equal_shape_and_contents(lg.mv_latch(x1_8v, x2_8v, x30_8v), mvarray('0XX000000XXXXXXX0XXXXXXX0XX10R110XX000000XXR0R0R0XXF001F0XX10R11'))
|
||||
assert_equal_shape_and_contents(lg.mv_latch(x1_8v, x2_8v, x31_8v), mvarray('1XX01F001XXXXXXX1XXXXXXX1XX111111XX01F001XXR110R1XXF1F1F1XX11111'))
|
||||
|
||||
|
||||
def test_bparray():
|
||||
|
||||
ary = lg.BPArray(4)
|
||||
assert ary.length == 1
|
||||
assert len(ary) == 1
|
||||
assert ary.width == 4
|
||||
bpa = bparray('0X-1PRFN')
|
||||
assert bpa.shape == (8, 3, 1)
|
||||
|
||||
ary = lg.BPArray((3, 2))
|
||||
assert ary.length == 2
|
||||
assert len(ary) == 2
|
||||
assert ary.width == 3
|
||||
bpa = bparray('0X-1PRFN-')
|
||||
assert bpa.shape == (9, 3, 1)
|
||||
|
||||
assert lg.MVArray(lg.BPArray("01", m=2))[0] == '01'
|
||||
assert lg.MVArray(lg.BPArray("0X-1", m=4))[0] == '0X-1'
|
||||
assert lg.MVArray(lg.BPArray("0X-1PRFN", m=8))[0] == '0X-1PRFN'
|
||||
bpa = bparray('000', '001', '010', '011', '100', '101', '110', '111')
|
||||
assert bpa.shape == (3, 3, 1)
|
||||
|
||||
x1_2v = lg.BPArray("0011", m=2)
|
||||
x2_2v = lg.BPArray("0101", m=2)
|
||||
x1_4v = lg.BPArray("0000XXXX----1111", m=4)
|
||||
x2_4v = lg.BPArray("0X-10X-10X-10X-1", m=4)
|
||||
x1_8v = lg.BPArray("00000000XXXXXXXX--------11111111PPPPPPPPRRRRRRRRFFFFFFFFNNNNNNNN", m=8)
|
||||
x2_8v = lg.BPArray("0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN0X-1PRFN", m=8)
|
||||
bpa = bparray('000', '001', '010', '011', '100', '101', '110', '111', 'RFX')
|
||||
assert bpa.shape == (3, 3, 2)
|
||||
|
||||
out_2v = lg.BPArray((4, 1), m=2)
|
||||
out_4v = lg.BPArray((16, 1), m=4)
|
||||
out_8v = lg.BPArray((64, 1), m=8)
|
||||
assert_equal_shape_and_contents(bp_to_mv(bparray('0X-1PRFN'))[:,0], mvarray('0X-1PRFN'))
|
||||
assert_equal_shape_and_contents(bparray('0X-1PRFN'), mv_to_bp(mvarray('0X-1PRFN')))
|
||||
|
||||
lg.bp_buf(out_2v.data, x1_2v.data)
|
||||
lg.bp_buf(out_4v.data, x1_4v.data)
|
||||
lg.bp_buf(out_8v.data, x1_8v.data)
|
||||
x1_8v = bparray('00000000XXXXXXXX--------11111111PPPPPPPPRRRRRRRRFFFFFFFFNNNNNNNN')
|
||||
x2_8v = bparray('0X-1PRFN'*8)
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '0011'
|
||||
assert lg.MVArray(out_4v)[0] == '0000XXXXXXXX1111'
|
||||
assert lg.MVArray(out_8v)[0] == '00000000XXXXXXXXXXXXXXXX11111111PPPPPPPPRRRRRRRRFFFFFFFFNNNNNNNN'
|
||||
out_8v = np.empty((64, 3, 1), dtype=np.uint8)
|
||||
|
||||
lg.bp_not(out_2v.data, x1_2v.data)
|
||||
lg.bp_not(out_4v.data, x1_4v.data)
|
||||
lg.bp_not(out_8v.data, x1_8v.data)
|
||||
assert_equal_shape_and_contents(bp_to_mv(lg.bp8v_buf(out_8v, x1_8v))[:,0], mvarray('00000000XXXXXXXXXXXXXXXX11111111PPPPPPPPRRRRRRRRFFFFFFFFNNNNNNNN'))
|
||||
assert_equal_shape_and_contents(bp_to_mv(lg.bp8v_or(out_8v, x1_8v, x2_8v))[:,0], mvarray('0XX1PRFNXXX1XXXXXXX1XXXX11111111PXX1PRFNRXX1RRNNFXX1FNFNNXX1NNNN'))
|
||||
assert_equal_shape_and_contents(bp_to_mv(lg.bp8v_and(out_8v, x1_8v, x2_8v))[:,0], mvarray('000000000XXXXXXX0XXXXXXX0XX1PRFN0XXPPPPP0XXRPRPR0XXFPPFF0XXNPRFN'))
|
||||
assert_equal_shape_and_contents(bp_to_mv(lg.bp8v_xor(out_8v, x1_8v, x2_8v))[:,0], mvarray('0XX1PRFNXXXXXXXXXXXXXXXX1XX0NFRPPXXNPRFNRXXFRPNFFXXRFNPRNXXPNFRP'))
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '1100'
|
||||
assert lg.MVArray(out_4v)[0] == '1111XXXXXXXX0000'
|
||||
assert lg.MVArray(out_8v)[0] == '11111111XXXXXXXXXXXXXXXX00000000NNNNNNNNFFFFFFFFRRRRRRRRPPPPPPPP'
|
||||
x30_8v = bparray('0000000000000000000000000000000000000000000000000000000000000000')
|
||||
x31_8v = bparray('1111111111111111111111111111111111111111111111111111111111111111')
|
||||
|
||||
lg.bp_or(out_2v.data, x1_2v.data, x2_2v.data)
|
||||
lg.bp_or(out_4v.data, x1_4v.data, x2_4v.data)
|
||||
lg.bp_or(out_8v.data, x1_8v.data, x2_8v.data)
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '0111'
|
||||
assert lg.MVArray(out_4v)[0] == '0XX1XXX1XXX11111'
|
||||
assert lg.MVArray(out_8v)[0] == '0XX1PRFNXXX1XXXXXXX1XXXX11111111PXX1PRFNRXX1RRNNFXX1FNFNNXX1NNNN'
|
||||
|
||||
lg.bp_and(out_2v.data, x1_2v.data, x2_2v.data)
|
||||
lg.bp_and(out_4v.data, x1_4v.data, x2_4v.data)
|
||||
lg.bp_and(out_8v.data, x1_8v.data, x2_8v.data)
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '0001'
|
||||
assert lg.MVArray(out_4v)[0] == '00000XXX0XXX0XX1'
|
||||
assert lg.MVArray(out_8v)[0] == '000000000XXXXXXX0XXXXXXX0XX1PRFN0XXPPPPP0XXRPRPR0XXFPPFF0XXNPRFN'
|
||||
|
||||
lg.bp_xor(out_2v.data, x1_2v.data, x2_2v.data)
|
||||
lg.bp_xor(out_4v.data, x1_4v.data, x2_4v.data)
|
||||
lg.bp_xor(out_8v.data, x1_8v.data, x2_8v.data)
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '0110'
|
||||
assert lg.MVArray(out_4v)[0] == '0XX1XXXXXXXX1XX0'
|
||||
assert lg.MVArray(out_8v)[0] == '0XX1PRFNXXXXXXXXXXXXXXXX1XX0NFRPPXXNPRFNRXXFRPNFFXXRFNPRNXXPNFRP'
|
||||
|
||||
x30_2v = lg.BPArray("0000", m=2)
|
||||
x30_4v = lg.BPArray("0000000000000000", m=4)
|
||||
x30_8v = lg.BPArray("0000000000000000000000000000000000000000000000000000000000000000", m=8)
|
||||
|
||||
lg.bp_latch(out_2v.data, x1_2v.data, x2_2v.data, x30_2v.data)
|
||||
lg.bp_latch(out_4v.data, x1_4v.data, x2_4v.data, x30_4v.data)
|
||||
lg.bp_latch(out_8v.data, x1_8v.data, x2_8v.data, x30_8v.data)
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '0001'
|
||||
assert lg.MVArray(out_4v)[0] == '0XX00XXX0XXX0XX1'
|
||||
assert lg.MVArray(out_8v)[0] == '0XX000000XXXXXXX0XXXXXXX0XX10R110XX000000XXR0R0R0XXF001F0XX10R11'
|
||||
|
||||
x31_2v = lg.BPArray("1111", m=2)
|
||||
x31_4v = lg.BPArray("1111111111111111", m=4)
|
||||
x31_8v = lg.BPArray("1111111111111111111111111111111111111111111111111111111111111111", m=8)
|
||||
|
||||
lg.bp_latch(out_2v.data, x1_2v.data, x2_2v.data, x31_2v.data)
|
||||
lg.bp_latch(out_4v.data, x1_4v.data, x2_4v.data, x31_4v.data)
|
||||
lg.bp_latch(out_8v.data, x1_8v.data, x2_8v.data, x31_8v.data)
|
||||
|
||||
assert lg.MVArray(out_2v)[0] == '1011'
|
||||
assert lg.MVArray(out_4v)[0] == '1XX01XXX1XXX1XX1'
|
||||
assert lg.MVArray(out_8v)[0] == '1XX01F001XXXXXXX1XXXXXXX1XX111111XX01F001XXR110R1XXF1F1F1XX11111'
|
||||
assert_equal_shape_and_contents(bp_to_mv(lg.bp8v_latch(out_8v, x1_8v, x2_8v, x30_8v))[:,0], mvarray('0XX000000XXXXXXX0XXXXXXX0XX10R110XX000000XXR0R0R0XXF001F0XX10R11'))
|
||||
assert_equal_shape_and_contents(bp_to_mv(lg.bp8v_latch(out_8v, x1_8v, x2_8v, x31_8v))[:,0], mvarray('1XX01F001XXXXXXX1XXXXXXX1XX111111XX01F001XXR110R1XXF1F1F1XX11111'))
|
||||
+139
-99
@@ -1,135 +1,175 @@
|
||||
from kyupy.logic_sim import LogicSim
|
||||
from kyupy import bench
|
||||
from kyupy.logic import MVArray, BPArray
|
||||
import numpy as np
|
||||
|
||||
from kyupy.logic_sim import LogicSim
|
||||
from kyupy import bench, logic, sim
|
||||
from kyupy.logic import mvarray, bparray, bp_to_mv, mv_to_bp
|
||||
|
||||
def assert_equal_shape_and_contents(actual, desired):
|
||||
desired = np.array(desired, dtype=np.uint8)
|
||||
assert actual.shape == desired.shape
|
||||
np.testing.assert_allclose(actual, desired)
|
||||
|
||||
def test_2v():
|
||||
c = bench.parse('input(x, y) output(a, o, n) a=and(x,y) o=or(x,y) n=not(x)')
|
||||
s = LogicSim(c, 4, m=2)
|
||||
assert len(s.interface) == 5
|
||||
mva = MVArray(['00000', '01000', '10000', '11000'], m=2)
|
||||
bpa = BPArray(mva)
|
||||
s.assign(bpa)
|
||||
s.propagate()
|
||||
s.capture(bpa)
|
||||
mva = MVArray(bpa)
|
||||
assert mva[0] == '00001'
|
||||
assert mva[1] == '01011'
|
||||
assert mva[2] == '10010'
|
||||
assert mva[3] == '11110'
|
||||
c = bench.parse(f'''
|
||||
input(i3, i2, i1, i0)
|
||||
output({",".join([f"o{i:02d}" for i in range(33)])})
|
||||
o00=BUF1(i0)
|
||||
o01=INV1(i0)
|
||||
o02=AND2(i0,i1)
|
||||
o03=AND3(i0,i1,i2)
|
||||
o04=AND4(i0,i1,i2,i3)
|
||||
o05=NAND2(i0,i1)
|
||||
o06=NAND3(i0,i1,i2)
|
||||
o07=NAND4(i0,i1,i2,i3)
|
||||
o08=OR2(i0,i1)
|
||||
o09=OR3(i0,i1,i2)
|
||||
o10=OR4(i0,i1,i2,i3)
|
||||
o11=NOR2(i0,i1)
|
||||
o12=NOR3(i0,i1,i2)
|
||||
o13=NOR4(i0,i1,i2,i3)
|
||||
o14=XOR2(i0,i1)
|
||||
o15=XOR3(i0,i1,i2)
|
||||
o16=XOR4(i0,i1,i2,i3)
|
||||
o17=XNOR2(i0,i1)
|
||||
o18=XNOR3(i0,i1,i2)
|
||||
o19=XNOR4(i0,i1,i2,i3)
|
||||
o20=AO21(i0,i1,i2)
|
||||
o21=OA21(i0,i1,i2)
|
||||
o22=AO22(i0,i1,i2,i3)
|
||||
o23=OA22(i0,i1,i2,i3)
|
||||
o24=AOI21(i0,i1,i2)
|
||||
o25=OAI21(i0,i1,i2)
|
||||
o26=AOI22(i0,i1,i2,i3)
|
||||
o27=OAI22(i0,i1,i2,i3)
|
||||
o28=AO211(i0,i1,i2,i3)
|
||||
o29=OA211(i0,i1,i2,i3)
|
||||
o30=AOI211(i0,i1,i2,i3)
|
||||
o31=OAI211(i0,i1,i2,i3)
|
||||
o32=MUX21(i0,i1,i2)
|
||||
''')
|
||||
s = LogicSim(c, 16, m=2)
|
||||
bpa = logic.bparray([f'{i:04b}'+('-'*(s.s_len-4)) for i in range(16)])
|
||||
s.s[0] = bpa
|
||||
s.s_to_c()
|
||||
s.c_prop()
|
||||
s.c_to_s()
|
||||
mva = logic.bp_to_mv(s.s[1])
|
||||
for res, exp in zip(logic.packbits(mva[4:], dtype=np.uint32), [
|
||||
sim.BUF1, sim.INV1,
|
||||
sim.AND2, sim.AND3, sim.AND4,
|
||||
sim.NAND2, sim.NAND3, sim.NAND4,
|
||||
sim.OR2, sim.OR3, sim.OR4,
|
||||
sim.NOR2, sim.NOR3, sim.NOR4,
|
||||
sim.XOR2, sim.XOR3, sim.XOR4,
|
||||
sim.XNOR2, sim.XNOR3, sim.XNOR4,
|
||||
sim.AO21, sim.OA21,
|
||||
sim.AO22, sim.OA22,
|
||||
sim.AOI21, sim.OAI21,
|
||||
sim.AOI22, sim.OAI22,
|
||||
sim.AO211, sim.OA211,
|
||||
sim.AOI211, sim.OAI211,
|
||||
sim.MUX21
|
||||
]):
|
||||
assert res == exp, f'Mismatch for SimPrim {sim.names[exp]} res={bin(res)} exp={bin(exp)}'
|
||||
|
||||
|
||||
def test_4v():
|
||||
c = bench.parse('input(x, y) output(a, o, n) a=and(x,y) o=or(x,y) n=not(x)')
|
||||
s = LogicSim(c, 16, m=4)
|
||||
assert len(s.interface) == 5
|
||||
mva = MVArray(['00000', '01000', '0-000', '0X000',
|
||||
'10000', '11000', '1-000', '1X000',
|
||||
'-0000', '-1000', '--000', '-X000',
|
||||
'X0000', 'X1000', 'X-000', 'XX000'], m=4)
|
||||
bpa = BPArray(mva)
|
||||
s.assign(bpa)
|
||||
s.propagate()
|
||||
s.capture(bpa)
|
||||
mva = MVArray(bpa)
|
||||
assert mva[0] == '00001'
|
||||
assert mva[1] == '01011'
|
||||
assert mva[2] == '0-0X1'
|
||||
assert mva[3] == '0X0X1'
|
||||
assert mva[4] == '10010'
|
||||
assert mva[5] == '11110'
|
||||
assert mva[6] == '1-X10'
|
||||
assert mva[7] == '1XX10'
|
||||
assert mva[8] == '-00XX'
|
||||
assert mva[9] == '-1X1X'
|
||||
assert mva[10] == '--XXX'
|
||||
assert mva[11] == '-XXXX'
|
||||
assert mva[12] == 'X00XX'
|
||||
assert mva[13] == 'X1X1X'
|
||||
assert mva[14] == 'X-XXX'
|
||||
assert mva[15] == 'XXXXX'
|
||||
s = LogicSim(c, 16, m=8) # FIXME: m=4
|
||||
assert s.s_len == 5
|
||||
bpa = bparray(
|
||||
'00---', '01---', '0----', '0X---',
|
||||
'10---', '11---', '1----', '1X---',
|
||||
'-0---', '-1---', '-----', '-X---',
|
||||
'X0---', 'X1---', 'X----', 'XX---')
|
||||
s.s[0] = bpa
|
||||
s.s_to_c()
|
||||
s.c_prop()
|
||||
s.c_to_s()
|
||||
mva = bp_to_mv(s.s[1])
|
||||
assert_equal_shape_and_contents(mva, mvarray(
|
||||
'--001', '--011', '--0X1', '--0X1',
|
||||
'--010', '--110', '--X10', '--X10',
|
||||
'--0XX', '--X1X', '--XXX', '--XXX',
|
||||
'--0XX', '--X1X', '--XXX', '--XXX'))
|
||||
|
||||
|
||||
def test_8v():
|
||||
c = bench.parse('input(x, y) output(a, o, n, xo) a=and(x,y) o=or(x,y) n=not(x) xo=xor(x,y)')
|
||||
s = LogicSim(c, 64, m=8)
|
||||
assert len(s.interface) == 6
|
||||
mva = MVArray(['000010', '010111', '0-0X1X', '0X0X1X', '0R0R1R', '0F0F1F', '0P0P1P', '0N0N1N',
|
||||
'100101', '111100', '1-X10X', '1XX10X', '1RR10F', '1FF10R', '1PP10N', '1NN10P',
|
||||
'-00XXX', '-1X1XX', '--XXXX', '-XXXXX', '-RXXXX', '-FXXXX', '-PXXXX', '-NXXXX',
|
||||
'X00XXX', 'X1X1XX', 'X-XXXX', 'XXXXXX', 'XRXXXX', 'XFXXXX', 'XPXXXX', 'XNXXXX',
|
||||
'R00RFR', 'R1R1FF', 'R-XXFX', 'RXXXFX', 'RRRRFP', 'RFPNFN', 'RPPRFR', 'RNRNFF',
|
||||
'F00FRF', 'F1F1RR', 'F-XXRX', 'FXXXRX', 'FRPNRN', 'FFFFRP', 'FPPFRF', 'FNFNRR',
|
||||
'P00PNP', 'P1P1NN', 'P-XXNX', 'PXXXNX', 'PRPRNR', 'PFPFNF', 'PPPPNP', 'PNPNNN',
|
||||
'N00NPN', 'N1N1PP', 'N-XXPX', 'NXXXPX', 'NRRNPF', 'NFFNPR', 'NPPNPN', 'NNNNPP'], m=8)
|
||||
bpa = BPArray(mva)
|
||||
s.assign(bpa)
|
||||
s.propagate()
|
||||
resp_bp = BPArray(bpa)
|
||||
s.capture(resp_bp)
|
||||
resp = MVArray(resp_bp)
|
||||
assert s.s_len == 6
|
||||
mva = mvarray(
|
||||
'000010', '010111', '0-0X1X', '0X0X1X', '0R0R1R', '0F0F1F', '0P0P1P', '0N0N1N',
|
||||
'100101', '111100', '1-X10X', '1XX10X', '1RR10F', '1FF10R', '1PP10N', '1NN10P',
|
||||
'-00XXX', '-1X1XX', '--XXXX', '-XXXXX', '-RXXXX', '-FXXXX', '-PXXXX', '-NXXXX',
|
||||
'X00XXX', 'X1X1XX', 'X-XXXX', 'XXXXXX', 'XRXXXX', 'XFXXXX', 'XPXXXX', 'XNXXXX',
|
||||
'R00RFR', 'R1R1FF', 'R-XXFX', 'RXXXFX', 'RRRRFP', 'RFPNFN', 'RPPRFR', 'RNRNFF',
|
||||
'F00FRF', 'F1F1RR', 'F-XXRX', 'FXXXRX', 'FRPNRN', 'FFFFRP', 'FPPFRF', 'FNFNRR',
|
||||
'P00PNP', 'P1P1NN', 'P-XXNX', 'PXXXNX', 'PRPRNR', 'PFPFNF', 'PPPPNP', 'PNPNNN',
|
||||
'N00NPN', 'N1N1PP', 'N-XXPX', 'NXXXPX', 'NRRNPF', 'NFFNPR', 'NPPNPN', 'NNNNPP')
|
||||
tests = np.copy(mva)
|
||||
tests[2:] = logic.UNASSIGNED
|
||||
bpa = mv_to_bp(tests)
|
||||
s.s[0] = bpa
|
||||
s.s_to_c()
|
||||
s.c_prop()
|
||||
s.c_to_s()
|
||||
resp = bp_to_mv(s.s[1])
|
||||
|
||||
for i in range(64):
|
||||
assert resp[i] == mva[i]
|
||||
exp_resp = np.copy(mva)
|
||||
exp_resp[:2] = logic.UNASSIGNED
|
||||
np.testing.assert_allclose(resp, exp_resp)
|
||||
|
||||
|
||||
def test_loop():
|
||||
c = bench.parse('q=dff(d) d=not(q)')
|
||||
s = LogicSim(c, 4, m=8)
|
||||
assert len(s.interface) == 1
|
||||
mva = MVArray([['0'], ['1'], ['R'], ['F']], m=8)
|
||||
assert s.s_len == 1
|
||||
mva = mvarray([['0'], ['1'], ['R'], ['F']])
|
||||
|
||||
s.assign(BPArray(mva))
|
||||
s.propagate()
|
||||
resp_bp = BPArray((len(s.interface), s.sims))
|
||||
s.capture(resp_bp)
|
||||
resp = MVArray(resp_bp)
|
||||
# TODO
|
||||
# s.assign(BPArray(mva))
|
||||
# s.propagate()
|
||||
# resp_bp = BPArray((len(s.interface), s.sims))
|
||||
# s.capture(resp_bp)
|
||||
# resp = MVArray(resp_bp)
|
||||
|
||||
assert resp[0] == '1'
|
||||
assert resp[1] == '0'
|
||||
assert resp[2] == 'F'
|
||||
assert resp[3] == 'R'
|
||||
# assert resp[0] == '1'
|
||||
# assert resp[1] == '0'
|
||||
# assert resp[2] == 'F'
|
||||
# assert resp[3] == 'R'
|
||||
|
||||
resp_bp = s.cycle(resp_bp)
|
||||
resp = MVArray(resp_bp)
|
||||
# resp_bp = s.cycle(resp_bp)
|
||||
# resp = MVArray(resp_bp)
|
||||
|
||||
assert resp[0] == '0'
|
||||
assert resp[1] == '1'
|
||||
assert resp[2] == 'R'
|
||||
assert resp[3] == 'F'
|
||||
# assert resp[0] == '0'
|
||||
# assert resp[1] == '1'
|
||||
# assert resp[2] == 'R'
|
||||
# assert resp[3] == 'F'
|
||||
|
||||
|
||||
def test_latch():
|
||||
c = bench.parse('input(d, t) output(q) q=latch(d, t)')
|
||||
s = LogicSim(c, 8, m=8)
|
||||
assert len(s.interface) == 4
|
||||
mva = MVArray(['00-0', '00-1', '01-0', '01-1', '10-0', '10-1', '11-0', '11-1'], m=8)
|
||||
exp = MVArray(['0000', '0011', '0100', '0100', '1000', '1011', '1111', '1111'], m=8)
|
||||
assert s.s_len == 4
|
||||
mva = mvarray('00-0', '00-1', '01-0', '01-1', '10-0', '10-1', '11-0', '11-1')
|
||||
exp = mvarray('0000', '0011', '0100', '0100', '1000', '1011', '1111', '1111')
|
||||
|
||||
resp = MVArray(s.cycle(BPArray(mva)))
|
||||
# TODO
|
||||
# resp = MVArray(s.cycle(BPArray(mva)))
|
||||
|
||||
for i in range(len(mva)):
|
||||
assert resp[i] == exp[i]
|
||||
# for i in range(len(mva)):
|
||||
# assert resp[i] == exp[i]
|
||||
|
||||
|
||||
def test_b01(mydir):
|
||||
c = bench.load(mydir / 'b01.bench')
|
||||
|
||||
# 2-valued
|
||||
s = LogicSim(c, 8, m=2)
|
||||
assert len(s.interface) == 9
|
||||
mva = MVArray((len(s.interface), 8), m=2)
|
||||
# mva.randomize()
|
||||
bpa = BPArray(mva)
|
||||
s.assign(bpa)
|
||||
s.propagate()
|
||||
s.capture(bpa)
|
||||
|
||||
# 8-valued
|
||||
s = LogicSim(c, 8, m=8)
|
||||
mva = MVArray((len(s.interface), 8), m=8)
|
||||
# mva.randomize()
|
||||
bpa = BPArray(mva)
|
||||
s.assign(bpa)
|
||||
s.propagate()
|
||||
s.capture(bpa)
|
||||
mva = np.zeros((s.s_len, 8), dtype=np.uint8)
|
||||
s.s[0] = mv_to_bp(mva)
|
||||
s.s_to_c()
|
||||
s.c_prop()
|
||||
s.c_to_s()
|
||||
bp_to_mv(s.s[1])
|
||||
+181
-49
@@ -1,5 +1,8 @@
|
||||
from kyupy import sdf, verilog
|
||||
import numpy as np
|
||||
|
||||
from kyupy import sdf, verilog, bench
|
||||
from kyupy.wave_sim import WaveSim, TMAX, TMIN
|
||||
from kyupy.techlib import SAED32, SAED90
|
||||
|
||||
def test_parse():
|
||||
test = '''
|
||||
@@ -16,71 +19,70 @@ def test_parse():
|
||||
(TEMPERATURE 25.00:25.00:25.00)
|
||||
(TIMESCALE 1ns)
|
||||
(CELL
|
||||
(CELLTYPE "b14")
|
||||
(INSTANCE)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(INTERCONNECT U621/ZN U19246/IN1 (0.000:0.000:0.000))
|
||||
(INTERCONNECT U13292/QN U19246/IN2 (0.001:0.001:0.001))
|
||||
(INTERCONNECT U15050/QN U19247/IN1 (0.000:0.000:0.000))
|
||||
(INTERCONNECT U13293/QN U19247/IN2 (0.000:0.000:0.000) (0.000:0.000:0.000))
|
||||
(CELLTYPE "b14")
|
||||
(INSTANCE)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(INTERCONNECT U621/ZN U19246/IN1 (0.000:0.000:0.000))
|
||||
(INTERCONNECT U13292/QN U19246/IN2 (0.001:0.001:0.001))
|
||||
(INTERCONNECT U15050/QN U19247/IN1 (0.000:0.000:0.000))
|
||||
(INTERCONNECT U13293/QN U19247/IN2 (0.000:0.000:0.000) (0.000:0.000:0.000))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(CELL
|
||||
(CELLTYPE "INVX2")
|
||||
(INSTANCE U78)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH INP ZN (0.201:0.227:0.227) (0.250:0.271:0.271))
|
||||
(CELLTYPE "INVX2")
|
||||
(INSTANCE U78)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH INP ZN (0.201:0.227:0.227) (0.250:0.271:0.271))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(CELL
|
||||
(CELLTYPE "SDFFARX1")
|
||||
(INSTANCE reg3_reg_1_0)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH (posedge CLK) Q (0.707:0.710:0.710) (0.737:0.740:0.740))
|
||||
(IOPATH (negedge RSTB) Q () (0.909:0.948:0.948))
|
||||
(IOPATH (posedge CLK) QN (0.585:0.589:0.589) (0.545:0.550:0.550))
|
||||
(IOPATH (negedge RSTB) QN (1.546:1.593:1.593) ())
|
||||
(CELLTYPE "SDFFARX1")
|
||||
(INSTANCE reg3_reg_1_0)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH (posedge CLK) Q (0.707:0.710:0.710) (0.737:0.740:0.740))
|
||||
(IOPATH (negedge RSTB) Q () (0.909:0.948:0.948))
|
||||
(IOPATH (posedge CLK) QN (0.585:0.589:0.589) (0.545:0.550:0.550))
|
||||
(IOPATH (negedge RSTB) QN (1.546:1.593:1.593) ())
|
||||
)
|
||||
)
|
||||
)
|
||||
(TIMINGCHECK
|
||||
(WIDTH (posedge CLK) (0.284:0.284:0.284))
|
||||
(WIDTH (negedge CLK) (0.642:0.642:0.642))
|
||||
(SETUP (posedge D) (posedge CLK) (0.544:0.553:0.553))
|
||||
(SETUP (negedge D) (posedge CLK) (0.620:0.643:0.643))
|
||||
(HOLD (posedge D) (posedge CLK) (-0.321:-0.331:-0.331))
|
||||
(HOLD (negedge D) (posedge CLK) (-0.196:-0.219:-0.219))
|
||||
(RECOVERY (posedge RSTB) (posedge CLK) (-1.390:-1.455:-1.455))
|
||||
(HOLD (posedge RSTB) (posedge CLK) (1.448:1.509:1.509))
|
||||
(SETUP (posedge SE) (posedge CLK) (0.662:0.670:0.670))
|
||||
(SETUP (negedge SE) (posedge CLK) (0.698:0.702:0.702))
|
||||
(HOLD (posedge SE) (posedge CLK) (-0.435:-0.444:-0.444))
|
||||
(HOLD (negedge SE) (posedge CLK) (-0.291:-0.295:-0.295))
|
||||
(SETUP (posedge SI) (posedge CLK) (0.544:0.544:0.544))
|
||||
(SETUP (negedge SI) (posedge CLK) (0.634:0.688:0.688))
|
||||
(HOLD (posedge SI) (posedge CLK) (-0.317:-0.318:-0.318))
|
||||
(HOLD (negedge SI) (posedge CLK) (-0.198:-0.247:-0.247))
|
||||
(WIDTH (negedge RSTB) (0.345:0.345:0.345))
|
||||
(TIMINGCHECK
|
||||
(WIDTH (posedge CLK) (0.284:0.284:0.284))
|
||||
(WIDTH (negedge CLK) (0.642:0.642:0.642))
|
||||
(SETUP (posedge D) (posedge CLK) (0.544:0.553:0.553))
|
||||
(SETUP (negedge D) (posedge CLK) (0.620:0.643:0.643))
|
||||
(HOLD (posedge D) (posedge CLK) (-0.321:-0.331:-0.331))
|
||||
(HOLD (negedge D) (posedge CLK) (-0.196:-0.219:-0.219))
|
||||
(RECOVERY (posedge RSTB) (posedge CLK) (-1.390:-1.455:-1.455))
|
||||
(HOLD (posedge RSTB) (posedge CLK) (1.448:1.509:1.509))
|
||||
(SETUP (posedge SE) (posedge CLK) (0.662:0.670:0.670))
|
||||
(SETUP (negedge SE) (posedge CLK) (0.698:0.702:0.702))
|
||||
(HOLD (posedge SE) (posedge CLK) (-0.435:-0.444:-0.444))
|
||||
(HOLD (negedge SE) (posedge CLK) (-0.291:-0.295:-0.295))
|
||||
(SETUP (posedge SI) (posedge CLK) (0.544:0.544:0.544))
|
||||
(SETUP (negedge SI) (posedge CLK) (0.634:0.688:0.688))
|
||||
(HOLD (posedge SI) (posedge CLK) (-0.317:-0.318:-0.318))
|
||||
(HOLD (negedge SI) (posedge CLK) (-0.198:-0.247:-0.247))
|
||||
(WIDTH (negedge RSTB) (0.345:0.345:0.345))
|
||||
)))
|
||||
'''
|
||||
df = sdf.parse(test)
|
||||
assert df.name == 'test'
|
||||
# print(f'DelayFile(name={df.name}, interconnects={len(df.interconnects)}, iopaths={len(df.iopaths)})')
|
||||
|
||||
|
||||
def test_b14(mydir):
|
||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||
assert df.name == 'b14'
|
||||
def test_b15(mydir):
|
||||
df = sdf.load(mydir / 'b15_2ig.sdf.gz')
|
||||
assert df.name == 'b15'
|
||||
|
||||
|
||||
def test_gates(mydir):
|
||||
c = verilog.load(mydir / 'gates.v')
|
||||
c = verilog.load(mydir / 'gates.v', tlib=SAED90)
|
||||
df = sdf.load(mydir / 'gates.sdf')
|
||||
lt = df.annotation(c, dataset=1)
|
||||
lt = df.iopaths(c, tlib=SAED90)[1]
|
||||
nand_a = c.cells['nandgate'].ins[0]
|
||||
nand_b = c.cells['nandgate'].ins[1]
|
||||
and_a = c.cells['andgate'].ins[0]
|
||||
@@ -97,3 +99,133 @@ def test_gates(mydir):
|
||||
|
||||
assert lt[and_b, 0, 0] == 0.375
|
||||
assert lt[and_b, 0, 1] == 0.370
|
||||
|
||||
|
||||
def test_nand_xor():
|
||||
c = bench.parse("""
|
||||
input(A1,A2)
|
||||
output(lt_1237_U91,lt_1237_U92)
|
||||
lt_1237_U91 = NAND2X0_RVT(A1,A2)
|
||||
lt_1237_U92 = XOR2X1_RVT(A1,A2)
|
||||
""")
|
||||
df = sdf.parse("""
|
||||
(DELAYFILE
|
||||
(CELL
|
||||
(CELLTYPE "NAND2X0_RVT")
|
||||
(INSTANCE lt_1237_U91)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH A1 Y (0.018:0.022:0.021) (0.017:0.019:0.019))
|
||||
(IOPATH A2 Y (0.021:0.024:0.024) (0.018:0.021:0.021))
|
||||
)
|
||||
)
|
||||
)
|
||||
(CELL
|
||||
(CELLTYPE "XOR2X1_RVT")
|
||||
(INSTANCE lt_1237_U92)
|
||||
(DELAY
|
||||
(ABSOLUTE
|
||||
(IOPATH (posedge A1) Y (0.035:0.038:0.038) (0.037:0.062:0.062))
|
||||
(IOPATH (negedge A1) Y (0.035:0.061:0.061) (0.036:0.040:0.040))
|
||||
(IOPATH (posedge A2) Y (0.042:0.043:0.043) (0.051:0.064:0.064))
|
||||
(IOPATH (negedge A2) Y (0.041:0.066:0.066) (0.051:0.053:0.053))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
""")
|
||||
d = df.iopaths(c, tlib=SAED32)[1]
|
||||
c.resolve_tlib_cells(SAED32)
|
||||
sim = WaveSim(c, delays=d, sims=16)
|
||||
|
||||
# input A1
|
||||
sim.s[0,0] = [0,1,0,1] * 4 # initial values 0101010101010101
|
||||
sim.s[1,0] = 0.0 # transition time
|
||||
sim.s[2,0] = [0,0,1,1] * 4 # final values 0011001100110011
|
||||
|
||||
# input A2
|
||||
sim.s[0,1] = ([0]*4 + [1]*4)*2 # initial values 0000111100001111
|
||||
sim.s[1,1] = 0.0 # transition time
|
||||
sim.s[2,1] = [0]*8 + [1]*8 # final values 0000000011111111
|
||||
|
||||
# A1: 0FR10FR10FR10FR1
|
||||
# A2: 0000FFFFRRRR1111
|
||||
# nand: 11111RNR1NFF1RF0
|
||||
# xor: 0FR1FPPRRNPF1RF0
|
||||
|
||||
sim.s_to_c()
|
||||
sim.c_prop()
|
||||
sim.c_to_s()
|
||||
|
||||
eat = sim.s[4,2:]
|
||||
lst = sim.s[5,2:]
|
||||
|
||||
# NAND-gate output
|
||||
assert np.allclose(eat[0], [
|
||||
TMAX, TMAX, TMAX, TMAX, TMAX,
|
||||
0.022, # FF -> rising Y: min(0.022, 0.024)
|
||||
TMAX, # RF: pulse filtered
|
||||
0.024, # falling A2 -> rising Y
|
||||
TMAX,
|
||||
TMAX, # FR: pulse filtered
|
||||
0.021, # RR -> falling Y: max(0.019, 0.021)
|
||||
0.021, # rising A2 -> falling Y
|
||||
TMAX,
|
||||
0.022, # falling A1 -> rising Y
|
||||
0.019, # rising A1 -> falling Y
|
||||
TMAX
|
||||
])
|
||||
|
||||
assert np.allclose(lst[0], [
|
||||
TMIN, TMIN, TMIN, TMIN, TMIN,
|
||||
0.022, # FF -> rising Y: min(0.022, 0.024)
|
||||
TMIN, # RF: pulse filtered
|
||||
0.024, # falling A2 -> rising Y
|
||||
TMIN,
|
||||
TMIN, # FR: pulse filtered
|
||||
0.021, # RR -> falling Y: max(0.019, 0.021)
|
||||
0.021, # rising A2 -> falling Y
|
||||
TMIN,
|
||||
0.022, # falling A1 -> rising Y
|
||||
0.019, # rising A1 -> falling Y
|
||||
TMIN
|
||||
])
|
||||
|
||||
#XOR-gate output
|
||||
assert np.allclose(eat[1], [
|
||||
TMAX,
|
||||
0.040, # A1:F -> Y:F
|
||||
0.038, # A1:R -> Y:R
|
||||
TMAX,
|
||||
0.053, # A2:F -> Y:F
|
||||
TMAX, # P filtered
|
||||
TMAX, # P filtered
|
||||
0.066, # A2:F -> Y:R
|
||||
0.043, # A2:R -> Y:R
|
||||
TMAX, # N filtered
|
||||
TMAX, # P filtered
|
||||
0.064, # A2:R -> Y:F
|
||||
TMAX,
|
||||
0.061, # A1:F -> Y:R
|
||||
0.062, # A1:R -> Y:F
|
||||
TMAX,
|
||||
])
|
||||
|
||||
assert np.allclose(lst[1], [
|
||||
TMIN,
|
||||
0.040, # A1:F -> Y:F
|
||||
0.038, # A1:R -> Y:R
|
||||
TMIN,
|
||||
0.053, # A2:F -> Y:F
|
||||
TMIN, # P filtered
|
||||
TMIN, # P filtered
|
||||
0.066, # A2:F -> Y:R
|
||||
0.043, # A2:R -> Y:R
|
||||
TMIN, # N filtered
|
||||
TMIN, # P filtered
|
||||
0.064, # A2:R -> Y:F
|
||||
TMIN,
|
||||
0.061, # A1:F -> Y:R
|
||||
0.062, # A1:R -> Y:F
|
||||
TMIN,
|
||||
])
|
||||
+13
-13
@@ -1,21 +1,21 @@
|
||||
from kyupy import stil, verilog
|
||||
from kyupy.techlib import SAED32
|
||||
|
||||
def test_b15(mydir):
|
||||
b15 = verilog.load(mydir / 'b15_2ig.v.gz', tlib=SAED32)
|
||||
|
||||
def test_b14(mydir):
|
||||
b14 = verilog.load(mydir / 'b14.v.gz')
|
||||
|
||||
s = stil.load(mydir / 'b14.stuck.stil.gz')
|
||||
s = stil.load(mydir / 'b15_2ig.sa_nf.stil.gz')
|
||||
assert len(s.signal_groups) == 10
|
||||
assert len(s.scan_chains) == 1
|
||||
assert len(s.calls) == 2163
|
||||
tests = s.tests(b14)
|
||||
resp = s.responses(b14)
|
||||
assert len(tests) > 0
|
||||
assert len(resp) > 0
|
||||
|
||||
s2 = stil.load(mydir / 'b14.transition.stil.gz')
|
||||
tests = s2.tests_loc(b14)
|
||||
resp = s2.responses(b14)
|
||||
assert len(s.calls) == 1357
|
||||
tests = s.tests(b15)
|
||||
resp = s.responses(b15)
|
||||
assert len(tests) > 0
|
||||
assert len(resp) > 0
|
||||
|
||||
s2 = stil.load(mydir / 'b15_2ig.tf_nf.stil.gz')
|
||||
tests = s2.tests_loc(b15)
|
||||
resp = s2.responses(b15)
|
||||
assert len(tests) > 0
|
||||
assert len(resp) > 0
|
||||
|
||||
+41
-4
@@ -1,8 +1,45 @@
|
||||
from kyupy import verilog
|
||||
|
||||
from kyupy.techlib import SAED90, SAED32
|
||||
|
||||
def test_b01(mydir):
|
||||
with open(mydir / 'b01.v', 'r') as f:
|
||||
modules = verilog.parse(f.read())
|
||||
assert modules is not None
|
||||
assert verilog.load(mydir / 'b01.v') is not None
|
||||
c = verilog.parse(f.read(), tlib=SAED90)
|
||||
assert c is not None
|
||||
assert verilog.load(mydir / 'b01.v', tlib=SAED90) is not None
|
||||
|
||||
assert len(c.nodes) == 139
|
||||
assert len(c.lines) == 203
|
||||
stats = c.stats
|
||||
assert stats['input'] == 6
|
||||
assert stats['output'] == 3
|
||||
assert stats['__seq__'] == 5
|
||||
|
||||
|
||||
def test_b15(mydir):
|
||||
c = verilog.load(mydir / 'b15_4ig.v.gz', tlib=SAED32)
|
||||
assert len(c.nodes) == 12067
|
||||
assert len(c.lines) == 20731
|
||||
stats = c.stats
|
||||
assert stats['input'] == 40
|
||||
assert stats['output'] == 71
|
||||
assert stats['__seq__'] == 417
|
||||
|
||||
|
||||
def test_gates(mydir):
|
||||
c = verilog.load(mydir / 'gates.v', tlib=SAED90)
|
||||
assert len(c.nodes) == 10
|
||||
assert len(c.lines) == 10
|
||||
stats = c.stats
|
||||
assert stats['input'] == 2
|
||||
assert stats['output'] == 2
|
||||
assert stats['__seq__'] == 0
|
||||
|
||||
|
||||
def test_halton2(mydir):
|
||||
c = verilog.load(mydir / 'rng_haltonBase2.synth_yosys.v', tlib=SAED90)
|
||||
assert len(c.nodes) == 146
|
||||
assert len(c.lines) == 210
|
||||
stats = c.stats
|
||||
assert stats['input'] == 2
|
||||
assert stats['output'] == 12
|
||||
assert stats['__seq__'] == 12
|
||||
+143
-125
@@ -1,150 +1,168 @@
|
||||
import numpy as np
|
||||
|
||||
from kyupy.wave_sim import WaveSim, WaveSimCuda, wave_eval, TMIN, TMAX
|
||||
from kyupy.wave_sim import WaveSim, WaveSimCuda, wave_eval_cpu, TMIN, TMAX
|
||||
from kyupy.logic_sim import LogicSim
|
||||
from kyupy import verilog, sdf, logic
|
||||
from kyupy.logic import MVArray, BPArray
|
||||
from kyupy import logic, bench, sim
|
||||
from kyupy.logic import mvarray
|
||||
|
||||
def test_nand_delays():
|
||||
op = (sim.NAND4, 4, 0, 1, 2, 3, -1, 0, 0)
|
||||
#op = (0b0111, 4, 0, 1)
|
||||
c = np.full((5*16, 1), TMAX) # 5 waveforms of capacity 16
|
||||
c_locs = np.zeros((5,), dtype='int')
|
||||
c_caps = np.zeros((5,), dtype='int')
|
||||
|
||||
for i in range(5): c_locs[i], c_caps[i] = i*16, 16 # 1:1 mapping
|
||||
|
||||
def test_wave_eval():
|
||||
# SDF specifies IOPATH delays with respect to output polarity
|
||||
# SDF pulse rejection value is determined by IOPATH causing last transition and polarity of last transition
|
||||
line_times = np.zeros((3, 2, 2))
|
||||
line_times[0, 0, 0] = 0.1 # A -> Z rise delay
|
||||
line_times[0, 0, 1] = 0.2 # A -> Z fall delay
|
||||
line_times[0, 1, 0] = 0.1 # A -> Z negative pulse limit (terminate in rising Z)
|
||||
line_times[0, 1, 1] = 0.2 # A -> Z positive pulse limit
|
||||
line_times[1, 0, 0] = 0.3 # as above for B -> Z
|
||||
line_times[1, 0, 1] = 0.4
|
||||
line_times[1, 1, 0] = 0.3
|
||||
line_times[1, 1, 1] = 0.4
|
||||
delays = np.zeros((1, 5, 2, 2))
|
||||
delays[0, 0, 0, 0] = 0.1 # A -> Z rise delay
|
||||
delays[0, 0, 0, 1] = 0.2 # A -> Z fall delay
|
||||
delays[0, 0, 1, 0] = 0.1 # A -> Z negative pulse limit (terminate in rising Z)
|
||||
delays[0, 0, 1, 1] = 0.2 # A -> Z positive pulse limit
|
||||
delays[0, 1, :, 0] = 0.3 # as above for B -> Z
|
||||
delays[0, 1, :, 1] = 0.4
|
||||
delays[0, 2, :, 0] = 0.5 # as above for C -> Z
|
||||
delays[0, 2, :, 1] = 0.6
|
||||
delays[0, 3, :, 0] = 0.7 # as above for D -> Z
|
||||
delays[0, 3, :, 1] = 0.8
|
||||
|
||||
state = np.zeros((3*16, 1)) + TMAX # 3 waveforms of capacity 16
|
||||
state[::16, 0] = 16 # first entry is capacity
|
||||
a = state[0:16, 0]
|
||||
b = state[16:32, 0]
|
||||
z = state[32:, 0]
|
||||
sat = np.zeros((3, 3), dtype='int')
|
||||
sat[0] = 0, 16, 0
|
||||
sat[1] = 16, 16, 0
|
||||
sat[2] = 32, 16, 0
|
||||
simctl_int = np.asarray([0], dtype=np.int32)
|
||||
|
||||
sdata = np.asarray([1, -1, 0, 0], dtype='float32')
|
||||
def wave_assert(inputs, output):
|
||||
for i, a in zip(inputs, c.reshape(-1,16)): a[:len(i)] = i
|
||||
wave_eval_cpu(op, c, c_locs, c_caps, 0, delays, simctl_int)
|
||||
for i, v in enumerate(output): np.testing.assert_allclose(c.reshape(-1,16)[4,i], v)
|
||||
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMIN
|
||||
wave_assert([[TMAX,TMAX],[TMAX,TMAX],[TMIN,TMAX],[TMIN,TMAX]], [TMIN,TMAX]) # NAND(0,0,1,1) => 1
|
||||
wave_assert([[TMIN,TMAX],[TMAX,TMAX],[TMIN,TMAX],[TMIN,TMAX]], [TMIN,TMAX]) # NAND(1,0,1,1) => 1
|
||||
wave_assert([[TMIN,TMAX],[TMIN,TMAX],[TMIN,TMAX],[TMIN,TMAX]], [TMAX]) # NAND(1,1,1,1) => 0
|
||||
|
||||
a[0] = TMIN
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMIN
|
||||
|
||||
b[0] = TMIN
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMAX
|
||||
|
||||
a[0] = 1 # A _/^^^
|
||||
b[0] = 2 # B __/^^
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMIN # ^^^\___ B -> Z fall delay
|
||||
assert z[1] == 2.4
|
||||
assert z[2] == TMAX
|
||||
|
||||
a[0] = TMIN # A ^^^^^^
|
||||
b[0] = TMIN # B ^^^\__
|
||||
b[1] = 2
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == 2.3 # ___/^^^ B -> Z rise delay
|
||||
assert z[1] == TMAX
|
||||
|
||||
# pos pulse of 0.35 at B -> 0.45 after delays
|
||||
a[0] = TMIN # A ^^^^^^^^
|
||||
b[0] = TMIN
|
||||
b[1] = 2 # B ^^\__/^^
|
||||
b[2] = 2.35
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == 2.3 # __/^^\__
|
||||
assert z[1] == 2.75
|
||||
assert z[2] == TMAX
|
||||
|
||||
# neg pulse of 0.45 at B -> 0.35 after delays
|
||||
a[0] = TMIN # A ^^^^^^^^
|
||||
b[0] = 2 # B __/^^\__
|
||||
b[1] = 2.45
|
||||
b[2] = TMAX
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMIN # ^^\__/^^
|
||||
assert z[1] == 2.4
|
||||
assert z[2] == 2.75
|
||||
assert z[3] == TMAX
|
||||
|
||||
# neg pulse of 0.35 at B -> 0.25 after delays (filtered)
|
||||
a[0] = TMIN # A ^^^^^^^^
|
||||
b[0] = 2 # B __/^^\__
|
||||
b[1] = 2.35
|
||||
b[2] = TMAX
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMIN # ^^^^^^
|
||||
assert z[1] == TMAX
|
||||
|
||||
# pos pulse of 0.25 at B -> 0.35 after delays (filtered)
|
||||
a[0] = TMIN # A ^^^^^^^^
|
||||
b[0] = TMIN
|
||||
b[1] = 2 # B ^^\__/^^
|
||||
b[2] = 2.25
|
||||
wave_eval((0b0111, 2, 0, 1), state, sat, 0, line_times, sdata)
|
||||
assert z[0] == TMAX # ______
|
||||
# Keep inputs C=1 and D=1.
|
||||
wave_assert([[1,TMAX],[2,TMAX]], [TMIN,2.4,TMAX]) # _/⎺⎺⎺ NAND __/⎺⎺ => ⎺⎺⎺\___ (B->Z fall delay)
|
||||
wave_assert([[TMIN,TMAX],[TMIN,2,TMAX]], [2.3,TMAX]) # ⎺⎺⎺⎺⎺ NAND ⎺⎺\__ => ___/⎺⎺⎺ (B->Z rise delay)
|
||||
wave_assert([[TMIN,TMAX],[TMIN,2,2.35,TMAX]], [2.3,2.75,TMAX]) # ⎺⎺⎺⎺⎺ NAND ⎺\_/⎺ => __/⎺⎺\_ (pos pulse, .35@B -> .45@Z)
|
||||
wave_assert([[TMIN,TMAX],[TMIN,2,2.25,TMAX]], [TMAX]) # ⎺⎺⎺⎺⎺ NAND ⎺\_/⎺ => _______ (pos pulse, .25@B -> .35@Z, filtered)
|
||||
wave_assert([[TMIN,TMAX],[2,2.45,TMAX]], [TMIN,2.4,2.75,TMAX]) # ⎺⎺⎺⎺⎺ NAND _/⎺\_ => ⎺⎺\_/⎺⎺ (neg pulse, .45@B -> .35@Z)
|
||||
wave_assert([[TMIN,TMAX],[2,2.35,TMAX]], [TMIN,TMAX]) # ⎺⎺⎺⎺⎺ NAND _/⎺\_ => ⎺⎺⎺⎺⎺⎺⎺ (neg pulse, .35@B -> .25@Z, filtered)
|
||||
|
||||
|
||||
def compare_to_logic_sim(wsim):
|
||||
tests = MVArray((len(wsim.interface), wsim.sims))
|
||||
def test_tiny_circuit():
|
||||
c = bench.parse('input(x, y) output(a, o, n) a=and(x,y) o=or(x,y) n=not(x)')
|
||||
delays = np.full((1, len(c.lines), 2, 2), 1.0) # unit delay for all lines
|
||||
wsim = WaveSim(c, delays)
|
||||
assert wsim.s.shape[1] == 5
|
||||
|
||||
# values for x
|
||||
wsim.s[:3,0,0] = 0, 10, 0
|
||||
wsim.s[:3,0,1] = 0, 20, 1
|
||||
wsim.s[:3,0,2] = 1, 30, 0
|
||||
wsim.s[:3,0,3] = 1, 40, 1
|
||||
|
||||
# values for y
|
||||
wsim.s[:3,1,0] = 1, 50, 0
|
||||
wsim.s[:3,1,1] = 1, 60, 0
|
||||
wsim.s[:3,1,2] = 1, 70, 0
|
||||
wsim.s[:3,1,3] = 0, 80, 1
|
||||
|
||||
wsim.s_to_c()
|
||||
|
||||
x_c_loc = wsim.c_locs[wsim.ppi_offset+0] # check x waveforms
|
||||
np.testing.assert_allclose(wsim.c[x_c_loc:x_c_loc+3, 0], [TMAX, TMAX, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[x_c_loc:x_c_loc+3, 1], [20, TMAX, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[x_c_loc:x_c_loc+3, 2], [TMIN, 30, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[x_c_loc:x_c_loc+3, 3], [TMIN, TMAX, TMAX])
|
||||
|
||||
y_c_loc = wsim.c_locs[wsim.ppi_offset+1] # check y waveforms
|
||||
np.testing.assert_allclose(wsim.c[y_c_loc:y_c_loc+3, 0], [TMIN, 50, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[y_c_loc:y_c_loc+3, 1], [TMIN, 60, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[y_c_loc:y_c_loc+3, 2], [TMIN, 70, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[y_c_loc:y_c_loc+3, 3], [80, TMAX, TMAX])
|
||||
|
||||
wsim.c_prop()
|
||||
|
||||
a_c_loc = wsim.c_locs[wsim.ppo_offset+2] # check a waveforms
|
||||
np.testing.assert_allclose(wsim.c[a_c_loc:a_c_loc+3, 0], [TMAX, TMAX, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[a_c_loc:a_c_loc+3, 1], [21, 61, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[a_c_loc:a_c_loc+3, 2], [TMIN, 31, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[a_c_loc:a_c_loc+3, 3], [81, TMAX, TMAX])
|
||||
|
||||
o_c_loc = wsim.c_locs[wsim.ppo_offset+3] # check o waveforms
|
||||
np.testing.assert_allclose(wsim.c[o_c_loc:o_c_loc+3, 0], [TMIN, 51, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[o_c_loc:o_c_loc+3, 1], [TMIN, TMAX, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[o_c_loc:o_c_loc+3, 2], [TMIN, 71, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[o_c_loc:o_c_loc+3, 3], [TMIN, TMAX, TMAX])
|
||||
|
||||
n_c_loc = wsim.c_locs[wsim.ppo_offset+4] # check n waveforms
|
||||
np.testing.assert_allclose(wsim.c[n_c_loc:n_c_loc+3, 0], [TMIN, TMAX, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[n_c_loc:n_c_loc+3, 1], [TMIN, 21, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[n_c_loc:n_c_loc+3, 2], [31, TMAX, TMAX])
|
||||
np.testing.assert_allclose(wsim.c[n_c_loc:n_c_loc+3, 3], [TMAX, TMAX, TMAX])
|
||||
|
||||
wsim.c_to_s()
|
||||
|
||||
# check a captures
|
||||
np.testing.assert_allclose(wsim.s[3:7, 2, 0], [0, TMAX, TMIN, 0])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 2, 1], [0, 21, 61, 0])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 2, 2], [1, 31, 31, 0])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 2, 3], [0, 81, 81, 1])
|
||||
|
||||
# check o captures
|
||||
np.testing.assert_allclose(wsim.s[3:7, 3, 0], [1, 51, 51, 0])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 3, 1], [1, TMAX, TMIN, 1])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 3, 2], [1, 71, 71, 0])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 3, 3], [1, TMAX, TMIN, 1])
|
||||
|
||||
# check o captures
|
||||
np.testing.assert_allclose(wsim.s[3:7, 4, 0], [1, TMAX, TMIN, 1])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 4, 1], [1, 21, 21, 0])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 4, 2], [0, 31, 31, 1])
|
||||
np.testing.assert_allclose(wsim.s[3:7, 4, 3], [0, TMAX, TMIN, 0])
|
||||
|
||||
|
||||
def compare_to_logic_sim(wsim: WaveSim):
|
||||
choices = np.asarray([logic.ZERO, logic.ONE, logic.RISE, logic.FALL], dtype=np.uint8)
|
||||
rng = np.random.default_rng(10)
|
||||
tests.data[...] = rng.choice(choices, tests.data.shape)
|
||||
tests_bp = BPArray(tests)
|
||||
wsim.assign(tests_bp)
|
||||
wsim.propagate()
|
||||
cdata = wsim.capture()
|
||||
tests = rng.choice(choices, (wsim.s_len, wsim.sims))
|
||||
|
||||
resp = MVArray(tests)
|
||||
wsim.s[0] = (tests & 2) >> 1
|
||||
wsim.s[3] = (tests & 2) >> 1
|
||||
wsim.s[1] = 0.0
|
||||
wsim.s[2] = tests & 1
|
||||
wsim.s[6] = tests & 1
|
||||
|
||||
for iidx, inode in enumerate(wsim.interface):
|
||||
if len(inode.ins) > 0:
|
||||
for vidx in range(wsim.sims):
|
||||
resp.data[iidx, vidx] = logic.ZERO if cdata[iidx, vidx, 0] < 0.5 else logic.ONE
|
||||
# resp.set_value(vidx, iidx, 0 if cdata[iidx, vidx, 0] < 0.5 else 1)
|
||||
wsim.s_to_c()
|
||||
wsim.c_prop()
|
||||
wsim.c_to_s()
|
||||
|
||||
lsim = LogicSim(wsim.circuit, len(tests_bp))
|
||||
lsim.assign(tests_bp)
|
||||
lsim.propagate()
|
||||
exp_bp = BPArray(tests_bp)
|
||||
lsim.capture(exp_bp)
|
||||
exp = MVArray(exp_bp)
|
||||
resp = np.array(wsim.s[6], dtype=np.uint8) | (np.array(wsim.s[3], dtype=np.uint8)<<1)
|
||||
resp |= ((resp ^ (resp >> 1)) & 1) << 2 # transitions
|
||||
resp[wsim.pi_s_locs] = logic.UNASSIGNED
|
||||
|
||||
for i in range(8):
|
||||
exp_str = exp[i].replace('R', '1').replace('F', '0').replace('P', '0').replace('N', '1')
|
||||
res_str = resp[i].replace('R', '1').replace('F', '0').replace('P', '0').replace('N', '1')
|
||||
assert res_str == exp_str
|
||||
lsim = LogicSim(wsim.circuit, tests.shape[-1])
|
||||
lsim.s[0] = logic.mv_to_bp(tests)
|
||||
lsim.s_to_c()
|
||||
lsim.c_prop()
|
||||
lsim.c_to_s()
|
||||
exp = logic.bp_to_mv(lsim.s[1])
|
||||
|
||||
resp[resp == logic.PPULSE] = logic.ZERO
|
||||
resp[resp == logic.NPULSE] = logic.ONE
|
||||
|
||||
exp[exp == logic.PPULSE] = logic.ZERO
|
||||
exp[exp == logic.NPULSE] = logic.ONE
|
||||
|
||||
np.testing.assert_allclose(resp, exp)
|
||||
|
||||
|
||||
def test_b14(mydir):
|
||||
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||
lt = df.annotation(c)
|
||||
wsim = WaveSim(c, lt, 8)
|
||||
compare_to_logic_sim(wsim)
|
||||
def test_b15(b15_2ig_circuit, b15_2ig_delays):
|
||||
compare_to_logic_sim(WaveSim(b15_2ig_circuit, b15_2ig_delays, 8))
|
||||
|
||||
|
||||
def test_b14_strip_forks(mydir):
|
||||
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||
lt = df.annotation(c)
|
||||
wsim = WaveSim(c, lt, 8, strip_forks=True)
|
||||
compare_to_logic_sim(wsim)
|
||||
def test_b15_strip_forks(b15_2ig_circuit, b15_2ig_delays):
|
||||
compare_to_logic_sim(WaveSim(b15_2ig_circuit, b15_2ig_delays, 8, strip_forks=True))
|
||||
|
||||
|
||||
def test_b14_cuda(mydir):
|
||||
c = verilog.load(mydir / 'b14.v.gz', branchforks=True)
|
||||
df = sdf.load(mydir / 'b14.sdf.gz')
|
||||
lt = df.annotation(c)
|
||||
wsim = WaveSimCuda(c, lt, 8)
|
||||
compare_to_logic_sim(wsim)
|
||||
def test_b15_cuda(b15_2ig_circuit, b15_2ig_delays):
|
||||
compare_to_logic_sim(WaveSimCuda(b15_2ig_circuit, b15_2ig_delays, 8, strip_forks=True))
|
||||
Reference in new issue
Block a user