Skip to content

Commit a4619b9

Browse files
authored
Merge pull request #144 from ven-k/vk/logictables
Digital: Adds `Logic` and defines 9 logic levels, `StdULogicVector`, and `StdLogicVector`
2 parents 56e4bd9 + de1fc3d commit a4619b9

File tree

7 files changed

+319
-117
lines changed

7 files changed

+319
-117
lines changed

Project.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ version = "1.11.0"
77
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
88
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
99
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
10-
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
1110
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
1211

1312
[compat]
1413
IfElse = "0.1"
1514
ModelingToolkit = "8.26"
16-
OffsetArrays = "1"
1715
Symbolics = "4.9, 5"
1816
julia = "1.6"
1917

src/Electrical/Digital/logic.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
@enum Logic Uninitialized=1 ForcingUnknown ForcingZero ForcingOne HighImpedence WeakUnknown WeakZero WeakOne DontCare
2+
3+
const U = Uninitialized
4+
const X = ForcingUnknown
5+
const F0 = ForcingZero
6+
const F1 = ForcingOne
7+
const Z = HighImpedence
8+
const W = WeakUnknown
9+
const L = WeakZero
10+
const H = WeakOne
11+
const DC = DontCare
12+
13+
function Base.show(io::IO, ::MIME"text/plain", l::Logic)
14+
if Int(l) == 1
15+
print(io, "U")
16+
elseif Int(l) == 2
17+
print(io, "X")
18+
elseif Int(l) == 3
19+
print(io, "F0")
20+
elseif Int(l) == 4
21+
print(io, "F1")
22+
elseif Int(l) == 5
23+
print(io, "Z")
24+
elseif Int(l) == 6
25+
print(io, "W")
26+
elseif Int(l) == 7
27+
print(io, "L")
28+
elseif Int(l) == 8
29+
print(io, "H")
30+
elseif Int(l) == 9
31+
print(io, "DC")
32+
else
33+
print(io, "Invalid logic level: $l")
34+
end
35+
end
36+
37+
Base.zero(::Logic) = F0
38+
Base.zero(::Type{Logic}) = F0
39+
Base.one(::Logic) = F1
40+
Base.one(::Type{Logic}) = F1
41+
42+
# Helpers to convert 1 and 0 to their `Logic` counterparts
43+
function Base.convert(l::Type{Logic}, i::Number)
44+
if i == zero(i)
45+
zero(l)
46+
elseif i == one(i)
47+
one(l)
48+
else
49+
throw("$i isn't a valid `Logic` value")
50+
end
51+
end
52+
Base.convert(l::Type{Logic}, i::Logic) = i
53+
54+
get_logic_level(l::Logic) = Int(l)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Base: size, axes, getindex, setindex!
2+
3+
const LogicOrNumber = Union{Logic, Number}
4+
5+
struct StdULogicVector{N} <: AbstractArray{Logic, N}
6+
logic::Array{Logic, N}
7+
function StdULogicVector(l::Array)
8+
new{ndims(l)}(Array{Logic}(convert.(Logic, l)))
9+
end
10+
end
11+
12+
struct StdLogicVector{N} <: AbstractArray{Logic, N}
13+
logic::Array{Logic, N}
14+
function StdLogicVector(l::Array)
15+
new{ndims(l)}(Array{Logic}(convert.(Logic, l)))
16+
end
17+
end
18+
19+
const LogicVector = Union{StdULogicVector, StdLogicVector}
20+
21+
size(l::LogicVector) = size(l.logic)
22+
23+
axes(l::LogicVector) = axes(l.logic)
24+
25+
getindex(s::LogicVector, i::Int) = getindex(s.logic, i)
26+
function Base.getindex(s::LogicVector, i1::Int, i2::Int,
27+
I::Int...)
28+
getindex(s.logic, i1, i2, I...)
29+
end
30+
31+
setindex!(A::LogicVector, x::Logic, i1::Int) = setindex!(A.logic, x, i1)
32+
function Base.setindex!(A::LogicVector, x::Logic, i1::Int, i2::Int, I::Int...)
33+
setindex!(A.logic, x, i1, i2, I...)
34+
end
35+
36+
get_logic_level(s::LogicVector) = Int.(s.logic)
37+
38+
# predefined vectors
39+
const std_ulogic = StdULogicVector([U, X, F0, F1, Z, W, L, H, DC])
40+
const UX01 = StdULogicVector([U, X, F0, F1])
41+
const UX01Z = StdULogicVector([U, X, F0, F1, Z])
42+
const X01 = StdULogicVector([X, F0, F1])
43+
const X01Z = StdULogicVector([X, F0, F1, Z])

src/Electrical/Digital/tables.jl

Lines changed: 112 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,134 @@
1-
# 9-level logic
2-
@parameters X
3-
4-
logicmap = Dict(0 => 0,
5-
1 => 1,
6-
:U => 2, # Uninitialized
7-
:X => 3, # Unknown
8-
:Z => 4, # High Impedence
9-
:W => 5, # Weak Unknown
10-
:L => 6, # Weak Low
11-
:H => 7, # Weak High
12-
:D => 8) # Don't Care; standard representation is `-`
13-
14-
logic(l) =
15-
try
16-
logicmap[l]
17-
catch
18-
(ex)
19-
X
1+
struct LogicTable{N} <: AbstractArray{Logic, N}
2+
logic::Array{Logic, N}
3+
function LogicTable(l::Array{Logic})
4+
any(i -> i != 9, size(l)) &&
5+
throw(ArgumentError("Incorrect number of logic values are passed. A variable of type
6+
`LogicTable` must have nine entries corresponding to 9 logic levels"))
7+
new{ndims(l)}(l)
208
end
9+
end
10+
11+
Base.size(l::LogicTable) = size(l.logic)
2112

22-
# SISO NOT gate
23-
NotTable = OffsetArray([
24-
# 0 1 :U :X :Z :W :L :H :D
25-
1; 0; :U; :X; :X; :X; 1; 0; :X], 0:8)
13+
Base.axes(l::LogicTable) = axes(l.logic)
2614

27-
function _not(x)
28-
i = logic(x)
29-
typeof(i) != Int && return X
30-
NotTable[i]
15+
getindex(s::LogicTable, l::Logic) = getindex(s.logic, get_logic_level(l))
16+
function Base.getindex(s::LogicTable, i1::Logic, i2::Logic)
17+
getindex(s.logic, get_logic_level(i1), get_logic_level(i2))
18+
end
19+
function Base.getindex(s::LogicTable, i1::Logic, i2::Logic,
20+
I::Logic...)
21+
getindex(s.logic, get_logic_level(i1), get_logic_level(i2), get_logic_level(I...)...)
22+
end
23+
24+
getindex(s::LogicTable, l::Int) = getindex(s.logic, l)
25+
function getindex(s::LogicTable, i1::Int, i2::Int, I::Int...)
26+
getindex(s.logic, i1, i2, I...)
3127
end
32-
@register_symbolic _not(x)
3328

34-
# MISO AND gate
35-
AndTable = OffsetArray([
36-
# 0 1 :U :X :Z :W :L :H :D
37-
0 0 0 0 0 0 0 0 0 # 0
38-
0 1 :U :X :X :X 0 1 :X # 1
39-
0 :U :U :U :U :U 0 :U :U # :U
40-
0 :X :U :X :X :X 0 :X :X # :X
41-
0 :X :U :X :X :X 0 :X :X # :Z
42-
0 1 :U :X :X :X 0 :X :X # :W
43-
0 0 0 0 0 0 0 0 0 # :L
44-
0 1 :U :X :X :X 0 1 :X # :H
45-
0 :X :U :X :X :X 0 :X :X], 0:8, 0:8)
46-
47-
function _and2(a, b)
48-
i, j = logic(a), logic(b)
49-
(typeof(i) != Int || typeof(j) != Int) && return X
50-
AndTable[i, j]
29+
function Base.setindex!(A::LogicTable, x::Logic, i1::Int)
30+
setindex!(A.logic, x, i1)
5131
end
32+
function Base.setindex!(A::LogicTable, x::Logic, i1::Int, i2::Int, I::Int...)
33+
setindex!(A.logic, x, i1, i2, I...)
34+
end
35+
36+
get_logic_level(l::LogicTable) = Int.(l.logic)
37+
38+
# AND gate
39+
const AndTable = LogicTable([
40+
# U X F0 F1 Z W L H DC
41+
U U F0 U U U F0 U U # U
42+
U X F0 X X X F0 X X # X
43+
F0 F0 F0 F0 F0 F0 F0 F0 F0 # F0
44+
U X F0 F1 X X F0 F1 X # F1
45+
U X F0 X X X F0 X X # Z
46+
U X F0 X X X F0 X X # W
47+
F0 F0 F0 F0 F0 F0 F0 F0 F0 # L
48+
U X F0 F1 X X F0 F1 X # H
49+
U X F0 X X X F0 X X]) # DC
50+
51+
function _and2(a::Logic, b::Logic)
52+
AndTable[a, b]
53+
end
54+
_and2(a::Number, b::Logic) = _and2(convert(Logic, a), b)
55+
_and2(a::Logic, b::Number) = _and2(a, convert(Logic, b))
56+
_and2(a::Number, b::Number) = _and2(convert(Logic, a), convert(Logic, b))
57+
5258
function _and(x...)
53-
y = [_and2(x[1], x[1])]
54-
for i in 2:length(x)
55-
push!(y, _and2(x[i], y[i - 1]))
59+
y = x[1]
60+
for i in 2:lastindex(x)
61+
y = _and2(y, x[i])
5662
end
57-
return y[end]
63+
return y
5864
end
59-
@register_symbolic _and(x...)
65+
6066
@register_symbolic _and(a, b)
61-
@register_symbolic _and(a, b, c)
62-
@register_symbolic _and(a, b, c, d)
63-
@register_symbolic _and(a, b, c, d, e)
64-
65-
# MISO OR gate
66-
OrTable = OffsetArray([
67-
# 0 1 :U :X :Z :W :L :H :D
68-
0 1 :U :X :X :X 0 1 :X # 0
69-
1 1 1 1 1 1 1 1 1 # 1
70-
:U 1 :U :U :U :U :U 1 :U # :U
71-
:X 1 :U :X :X :X :X 1 :X # :X
72-
:X 1 :U :X :X :X :X 1 :X # :Z
73-
:X 1 :U :X :X :X :X 1 :X # :W
74-
0 1 :U :X :X :X 0 1 :X # :L
75-
1 1 1 1 1 1 1 1 1 # :H
76-
:X 1 :U :X :X :X :X 1 :X], 0:8, 0:8)
77-
78-
function _or2(a, b)
79-
i, j = logic(a), logic(b)
80-
(typeof(i) != Int || typeof(j) != Int) && return X
81-
OrTable[i, j]
67+
68+
# NOT gate
69+
const NotTable = LogicTable([U, X, F1, F0, X, X, F1, F0, X])
70+
71+
_not(x::Logic) = NotTable[x]
72+
_not(x::Number) = _not(convert(Logic, x))
73+
74+
@register_symbolic _not(x)
75+
76+
# OR gate
77+
const OrTable = LogicTable([
78+
# U X F0 F1 Z W L H DC
79+
U U U F1 U U U F1 U # U
80+
U X X F1 X X X F1 X # X
81+
U X F0 F1 X X F0 F1 X # F0
82+
F1 F1 F1 F1 F1 F1 F1 F1 F1 # F1
83+
U X X F1 X X X F1 X # Z
84+
U X X F1 X X X F1 X # W
85+
U X F0 F1 X X F0 F1 X # L
86+
F1 F1 F1 F1 F1 F1 F1 F1 F1 # H
87+
U X X F1 X X X F1 X]) # DC
88+
89+
function _or2(a::Logic, b::Logic)
90+
OrTable[a, b]
8291
end
92+
_or2(a::Number, b::Logic) = _or2(convert(Logic, a), b)
93+
_or2(a::Logic, b::Number) = _or2(a, convert(Logic, b))
94+
_or2(a::Number, b::Number) = _or2(convert(Logic, a), convert(Logic, b))
8395

8496
function _or(x...)
85-
y = [_or2(x[1], x[1])]
86-
for i in 2:length(x)
87-
push!(y, _or2(x[i], y[i - 1]))
97+
y = x[1]
98+
for i in 2:lastindex(x)
99+
y = _or2(y, x[i])
88100
end
89-
return y[end]
101+
return y
90102
end
91-
@register_symbolic _or(x...)
103+
92104
@register_symbolic _or(a, b)
93-
@register_symbolic _or(a, b, c)
94-
@register_symbolic _or(a, b, c, d)
95-
@register_symbolic _or(a, b, c, d, e)
96-
@register_symbolic _or(a, b, c, d, e, f, g, h)
97-
98-
# MISO :XOR gate
99-
100-
XorTable = OffsetArray([
101-
# 0 1 :U :X :Z :W :L :H :D
102-
0 1 :U :X :X :X 0 1 :X # 0
103-
1 0 :U :X :X :X 1 0 :X # 1
104-
:U :U :U :U :U :U :U :U :U # :U
105-
:X :X :U :X :X :X :X :X :X # :X
106-
:X :X :U :X :X :X :X :X :X # :Z
107-
:X :X :U :X :X :X :X :X :X # :W
108-
0 1 :U :X :X :X 0 1 :X # :L
109-
1 0 :U :X :X :X 1 0 :X # :H
110-
:X :X :U :X :X :X :X :X :X], 0:8, 0:8)
111-
112-
function _xor2(a, b)
113-
i, j = logic(a), logic(b)
114-
(typeof(i) != Int || typeof(j) != Int) && return X
115-
XorTable[i, j]
105+
106+
# XOR gate
107+
const XorTable = LogicTable([
108+
# U X F0 F1 Z W L H DC
109+
U U U U U U U U U # U
110+
U X X X X X X X X # X
111+
U X F0 F1 X X F0 F1 X # F0
112+
U X F1 F0 X X F1 F0 X # F1
113+
U X X X X X X X X # Z
114+
U X X X X X X X X # W
115+
U X F0 F1 X X F0 F1 X # L
116+
U X F1 F0 X X F1 F0 X # H
117+
U X X X X X X X X]) # DC
118+
119+
function _xor2(a::Logic, b::Logic)
120+
XorTable[a, b]
116121
end
122+
_xor2(a::Number, b::Logic) = _xor2(convert(Logic, a), b)
123+
_xor2(a::Logic, b::Number) = _xor2(a, convert(Logic, b))
124+
_xor2(a::Number, b::Number) = _xor2(convert(Logic, a), convert(Logic, b))
117125

118126
function _xor(x...)
119-
y = [_xor2(x[1], 0)]
120-
for i in 2:length(x)
121-
push!(y, _xor2(x[i], y[i - 1]))
127+
y = x[1]
128+
for i in 2:lastindex(x)
129+
y = _xor2(y, x[i])
122130
end
123-
return y[end]
131+
return y
124132
end
125-
@register_symbolic _xor(x...)
126-
@register_symbolic _xor(a, b)
127-
@register_symbolic _xor(a, b, c)
128-
@register_symbolic _xor(a, b, c, d)
129-
@register_symbolic _xor(a, b, c, d, e)
130133

131-
# TODO: revisit y[1] for all miso gates for 9-level logic
134+
@register_symbolic _xor(a, b)

src/Electrical/Electrical.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ This library contains electrical components to build up analog circuits.
55
module Electrical
66

77
using ModelingToolkit, Symbolics, IfElse
8-
using OffsetArrays
98
using ..Thermal: HeatPort
109
using ..Mechanical.Rotational: Flange, Support
1110
using ..Blocks: RealInput, RealOutput
@@ -26,14 +25,24 @@ include("Analog/sensors.jl")
2625
export Voltage, Current
2726
include("Analog/sources.jl")
2827

29-
# include("Digital/components.jl")
3028
# include("Digital/gates.jl")
31-
# include("Digital/tables.jl")
3229
# include("Digital/sources.jl")
3330

3431
# TODO:
3532
# - digital
3633
# - machines
3734
# - multi-phase
3835

36+
export Logic
37+
include("Digital/logic.jl")
38+
39+
export StdLogicVector, StdULogicVector,
40+
std_ulogic, UX01, UX01Z, X01, X01Z,
41+
get_logic_level
42+
include("Digital/logic_vectors.jl")
43+
44+
export LogicTable,
45+
AndTable, OrTable, NotTable, XorTable
46+
include("Digital/tables.jl")
47+
3948
end

0 commit comments

Comments
 (0)