Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
3dfc51d
Quick fix adding the minimum amount of code to get the functionality …
standanley Oct 7, 2019
8c92eb0
Fixed style in new test
standanley Oct 8, 2019
e744e1e
Fix indexing into one bit of a spice bus
standanley Oct 16, 2019
e72dda3
Merge pull request #1 from standanley/spice_bus_indexing
standanley Oct 16, 2019
deaea62
Merge remote-tracking branch 'upstream/master'
standanley Nov 12, 2019
311d6d3
Wrote background poke Thread class
standanley Nov 13, 2019
26a0eb4
Finished writing background poke interleaving but have not even run i…
standanley Nov 13, 2019
0368670
I think it is working for spice targets.
standanley Nov 13, 2019
95ddd0b
Working on tests for background pokes
standanley Nov 18, 2019
794d7a3
Changed location of unit conversion in spice_target
standanley Nov 18, 2019
2ff5d92
Added Print action and nothing more
standanley Nov 20, 2019
5276903
Added read to VerilogTarget but no implementation
standanley Nov 20, 2019
7c94e67
Reading now works for systemverilog targets
standanley Nov 21, 2019
78abb7c
Reads work for spice too, based on minimal testing
standanley Nov 21, 2019
64bd264
Edge finder is now working. Need to clean up prints
standanley Nov 22, 2019
6198fa2
Allow indexing into spice buses
standanley Nov 22, 2019
e5f9ecb
Phase measurement now working in spice
standanley Nov 22, 2019
6a61712
Deleted some debugging prints
standanley Nov 22, 2019
4272bb4
Fixed bug in phase measurement and added test
standanley Nov 23, 2019
8a23678
Merged spice_timing into read_action but some of the read_action test…
standanley Nov 23, 2019
35faadf
Changed background poke so it would not break spice reads. Still an i…
standanley Nov 23, 2019
893c859
Fixed default clock step
standanley Dec 3, 2019
7aa57ff
Fixed bug with clocks in background_poke
standanley Dec 5, 2019
bfeba86
Changed pwc to pwl conversion to allow two points within rt of each o…
standanley Dec 5, 2019
2dc8063
Changed spice_target to print stderr of simulation command
standanley Dec 5, 2019
ae39e7a
Marked read action as not implemented in verilator_target
standanley Dec 5, 2019
a6542d0
Bugfix and labeling of error output.
standanley Jan 6, 2020
4939b87
New read styles, decreased default step size in spice transient sim
standanley Jan 22, 2020
096a74f
fixed issue with block reads beyond the end of simulation time
standanley Jan 27, 2020
657e003
Got rid of some references to old style read using save_for_later. St…
standanley Feb 24, 2020
d3800dc
I think I finished the merge but I cannot import fault due to an issu…
standanley Feb 25, 2020
fef2299
Merge branch 'master' into combine_branches
standanley Feb 25, 2020
67db95b
Finished merge and fixed old bug with saves for Read action
standanley Mar 4, 2020
dfa0510
Removed many references to read action.
standanley Mar 4, 2020
1930f7c
Merge branch 'master' into combine_branches
standanley Mar 4, 2020
91e190b
Merge branch 'master' into combine_branches
standanley Mar 4, 2020
f14e6a4
Fixed mistake from earlier merge
standanley Mar 4, 2020
2421029
Changed background poke to a decorator
standanley Mar 4, 2020
764feb2
updated sv target to use new background poke decorator
standanley Mar 4, 2020
8181e6a
add timeout to buildkite flow
sgherbst Mar 5, 2020
d42104d
Merge pull request #221 from leonardt/timeout
leonardt Mar 6, 2020
b8e2087
Init synchronous tester
leonardt Mar 10, 2020
4e3176a
Require clock
leonardt Mar 10, 2020
2b7485a
Add verilator target
leonardt Mar 10, 2020
f1701c1
Use open API
leonardt Mar 10, 2020
c59cd16
Fix name
leonardt Mar 10, 2020
ec47f77
Fix whitespace
leonardt Mar 10, 2020
1f8ae6c
Style
leonardt Mar 11, 2020
ce80cb1
Merge pull request #222 from leonardt/sync-tester
leonardt Mar 11, 2020
5b42aaa
Release 3.0.8
leonardt Mar 11, 2020
620bebd
Add failing test case
cdonovick Mar 12, 2020
95234fc
Support MagmaProtocol
leonardt Mar 12, 2020
0c7820f
Fix style
leonardt Mar 13, 2020
6532ee5
Merge pull request #224 from leonardt/protocol
cdonovick Mar 13, 2020
97b5401
implement top_module for all simulators
sgherbst Mar 13, 2020
7e67172
fix bug related to external testbenches
sgherbst Mar 13, 2020
6b409df
remove new top_module test temporarily due to macOS issue
sgherbst Mar 13, 2020
6d3bb5b
add no_top_module escape hatch
sgherbst Mar 13, 2020
26f242a
fix some of the deprecation warnings
sgherbst Mar 13, 2020
2ce651c
finish fixing circuit declaration deprecation warnings
sgherbst Mar 13, 2020
ba3dd20
add some files to gitignore that are generated while running pytest
sgherbst Mar 13, 2020
b799181
fix a few more deprecation warnings
sgherbst Mar 13, 2020
7267b3e
fix pycodestyle warnings
sgherbst Mar 13, 2020
7b92980
fix deprecation warning
sgherbst Mar 13, 2020
87616e7
Merge pull request #225 from leonardt/top_module
sgherbst Mar 13, 2020
27e4878
add support for paths with spaces to vivado
sgherbst Mar 13, 2020
246f2bf
fix handling of define macros with quotes
sgherbst Mar 14, 2020
f8bd31e
Merge pull request #226 from leonardt/paths_w_spaces_2
sgherbst Mar 14, 2020
aeb708e
Release 3.0.9
sgherbst Mar 14, 2020
8742203
Merge pull request #227 from leonardt/v_3_0_9
leonardt Mar 17, 2020
cfa3237
Tiny change to avoid mantle comparison that broke on bit type
standanley Mar 17, 2020
30e621b
First pass of understanding mLingua waveforms
standanley Mar 19, 2020
f944500
Working on get_value in different domains. I think it works for syste…
standanley Mar 23, 2020
0f0f90b
Fix domain read for spice. Still some pending todos
standanley Mar 23, 2020
84edb56
Can now read frequency/phase with systemverilog target
standanley Mar 24, 2020
d0e7dad
Fixed a couple bugs in background poke
standanley Mar 25, 2020
eb22b9a
Edge find bug fix
standanley Mar 25, 2020
417361d
Edge find bug fix
standanley Mar 25, 2020
bf34111
Merge branch 'combine_branches' of https://github.com/standanley/faul…
standanley Mar 25, 2020
49ab608
Fix tiny bug with recent changes
standanley Mar 27, 2020
3af3399
Insert flags before other command options
leonardt Mar 30, 2020
7e9d190
Initial clocks to zero
leonardt Mar 30, 2020
a874eb2
Update tests
leonardt Mar 30, 2020
732729a
Merge pull request #229 from leonardt/init-clock-zero
leonardt Mar 31, 2020
02d746a
Merge pull request #228 from leonardt/flags-order
leonardt Mar 31, 2020
f98beb7
Release 3.0.10
leonardt Mar 31, 2020
ce9ae41
Merged in master
standanley Apr 2, 2020
a62a3b4
Add flatten method to real_type
standanley Apr 2, 2020
686b158
Merge branch 'add_flatten' into combine_branches
standanley Apr 2, 2020
7c5fe10
Delete traces of old Read action (replaced by GetValue)
standanley Apr 2, 2020
a255b2c
Fix floating point equality comparison
standanley Apr 13, 2020
b921caa
Fixes for arrays of analog and outputs that are arrays
standanley Apr 16, 2020
f990113
Slight update to verilog_target for domain_read
standanley Jun 3, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ steps:
# upload coverage results
bash <(curl -s https://codecov.io/bash)
label: "test"
timeout_in_minutes: 60
agents:
fault2: "true"
- command: |
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ dist
fault.egg-info
pytest.ini
vnc_logs
.coverage
.magma
coverage.xml
parser.out
parsetab.py
3 changes: 2 additions & 1 deletion fault/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from .wrapped_internal_port import WrappedVerilogInternalPort
from .real_type import RealIn, RealOut, RealKind, RealType
from .elect_type import ElectIn, ElectOut, ElectKind, ElectType
from .tester import Tester, SymbolicTester, PythonTester, TesterBase
from .tester import (Tester, SymbolicTester, PythonTester, TesterBase,
SynchronousTester)
from .power_tester import PowerTester
from .value import Value, AnyValue, UnknownValue, HiZ
import fault.random
Expand Down
29 changes: 28 additions & 1 deletion fault/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import fault
from fault.select_path import SelectPath
import fault.expression as expression
from fault.domain_read import domain_read


class Action(ABC):
Expand Down Expand Up @@ -76,6 +77,30 @@ def retarget(self, new_circuit, clock):
return cls(self.format_str, *new_ports)


class Read(Action):
def __init__(self, port, params=None):
super().__init__()
self.port = port
self.params = params

def __getattr__(self, name):
if name == 'value':
err_msg = f'value has not been set for {self}'
err_msg += ', did the simulation finish running yet?'
assert False, err_msg
else:
raise AttributeError

def __str__(self):
return f"Read({self.port.debug_name})"

def retarget(self, new_circuit, clock):
cls = type(self)
new_port = new_circuit.interface.ports[str(self.port.name)]
return cls(new_port)



def is_inout(port):
if isinstance(port, SelectPath):
port = port[-1]
Expand All @@ -94,10 +119,12 @@ def is_output(port):
return not port.is_output()


@domain_read
class GetValue(Action):
def __init__(self, port):
def __init__(self, port, params):
super().__init__()
self.port = port
self.params = params
self.value = None # value to be assigned after simulation

@property
Expand Down
236 changes: 236 additions & 0 deletions fault/background_poke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
from fault.actions import Poke
import heapq
import math
from functools import total_ordering
import copy
from fault.target import Target
from fault.actions import Delay


@total_ordering
class Thread():
# if sin wave dt is unspecified, use period/default_steps_per_cycle
default_steps_per_cycle = 10

# when checking clock value at time t, check time t+epsilon instead
# this avoids ambiguity when landing exactly on the clock edge
# Also, used to check whether a step was supposed to have happened exactly
# on a scheduled update, or is too early and we should reschedule
epsilon = 1e-18

def __init__(self, time, poke):
#print('creating thread for', poke, 'at time', time)
self.poke = copy.copy(poke)
self.poke.params = None
self.poke.delay = None
params = poke.delay
self.start = time
self.next_update = time
type_ = params.get('type', 'clock')

#print('type_ is', type_)
#print(params)

# Each type must set a get_val(t) function and a dt
if type_ == 'clock':
freq = params.get('freq', 1e6)
period = params.get('period', 1/freq)
freq = 1 / period
duty_cycle = params.get('duty_cycle', 0.5)
initial_value = params.get('initial_value', 0)

def get_val(t):
cycle_location = ((t - self.start + self.epsilon) / period) % 1
if initial_value == 0:
return 1 if cycle_location > (1 - duty_cycle) else 0
else:
return 1 if cycle_location < duty_cycle else 0

self.get_val = get_val
self.dt = period/2

elif type_ == 'sin':
freq = params.get('freq', 1e6)
period = params.get('period', 1/freq)
freq = 1 / period
amplitude = params.get('amplitude', 1)
offset = params.get('offset', 0)
phase_degrees = params.get('phase_degrees', 0)
conv = math.pi / 180.0
phase_radians = params.get('phase_radians', phase_degrees * conv)

def get_val(t):
x = math.sin((t-self.start)*freq*2*math.pi + phase_radians)
return amplitude * x + offset

self.get_val = get_val
self.dt = params.get('dt', 1 / (freq*self.default_steps_per_cycle))

def step(self, t):
'''
Returns a new Poke object with the correct value set for time t.
Sets the port and value but NOT the delay.
'''
# TODO don't poke at the same time twice
missed_update_msg = 'Background Poke thread not updated in time'
assert t <= self.next_update + self.epsilon, missed_update_msg
if abs(t - self.next_update) < self.epsilon:
self.next_update = t + self.dt
value = self.get_val(t)
poke = copy.copy(self.poke)
poke.value = value
return poke

def __lt__(self, other):
return self.next_update < other


class ThreadPool():
# if the next background update is within epsilon of the next manual
# update, then the background one comes first
# Which comes first is arbitrary, but this epsilon makes it consistent
epsilon = 1e-18

def __init__(self, time):
self.t = time
self.background_threads = []
self.active_ports = set()

def get_next_update_time(self):
if len(self.background_threads) == 0:
return float('inf')
else:
return self.background_threads[0].next_update

def delay(self, t_delay):
'''
Create a list of actions that need to happen during this delay.
Returns (free_time, actions), where free_time is the delay that should
happen before the first action in actions.
'''
#print('Thread pool is doing a delay of ', t_delay, 'at time', self.t)
t = self.t
t_end = self.t + t_delay
# note that free_time here is actually the free time until the next pool update,
# the actual time returned is until the next action and might be less than free_time
free_time = self.get_next_update_time() - self.t
if free_time > t_delay:
self.t = t_end
return (t_delay, [])
else:
actions = []
t += free_time;
#print('entering while loop')
while self.get_next_update_time() <= t_end + self.epsilon:
thread = heapq.heappop(self.background_threads)
action = thread.step(t)
heapq.heappush(self.background_threads, thread)

# we had to put the thread back on the heap in order to
# calculate the next update
next_thing_time = min(self.get_next_update_time(), t_end)
#print('\ncalculated next thing time', next_thing_time, 'at time', t)
action.delay = next_thing_time - t
#print('also adding action', action, 'delay', action.delay)
t = next_thing_time
actions.append(action)

# t_end has less floating point error than t
self.t = t_end
#print('ending updates at time', t_end)
return (free_time, actions)

def add(self, background_poke):
error_msg = 'Cannot add existing background thread'
assert background_poke.port not in self.active_ports, error_msg
self.active_ports.add(background_poke.port)
thread = Thread(self.t, background_poke)
heapq.heappush(self.background_threads, thread)

def remove(self, port):
self.active_ports.remove(port)
for thread in self.background_threads:
if thread.poke.port is port:
offender = thread
self.background_threads.remove(offender)
heapq.heapify(self.background_threads)
poke = offender.step(self.t)
poke.delay = 0
if poke is None:
return []
else:
return [poke]

def process(self, action, delay):
new_action_list = []
is_background = (isinstance(action, Poke)
and type(action.delay) == dict)

# check whether this is a poke taking over a background port
if (isinstance(action, Poke)
and action.port in self.active_ports):
new_action_list += self.remove(action.port)

# if the new port is background we must add it before doing delay
if is_background:
self.add(action)

# we might cut action's delay short to allow some background pokes
new_delay, actions = self.delay(delay)

# now we add this (shortened) action back in
if not is_background:
# TODO: we used to use copies of the action so we weren't editing
# the delay of an action owned by someone else. But with the new
# Read action it's important that the object doesn't change
# because the user is holding a pointer to the old Read object
if isinstance(action, Delay):
action.time = new_delay
else:
action.delay = new_delay
new_action_list.append(action)
#new_action = copy.copy(action)
#new_action.delay = new_delay
#new_action_list.append(new_action)

new_action_list += actions
#print('ended up with', len(new_action_list), 'new actions')
#print('delay of first', new_action_list[0].delay, 'last', new_action_list[-1].delay)
#if len(new_action_list) > 1:
# for action in new_action_list:
# print('\t', action, '\t', action.delay)
return new_action_list


def process_action_list(actions, clock_step_delay):
"""
Replace Pokes with background_params with many individual pokes.
Automatically interleaves multiple background tasks with other pokes.
Throws a NotImplementedError if there's a background task during an
interval of time not known at compile time.
"""

def get_delay(a):
if not hasattr(a, 'delay'):
return getattr(a, 'time', 0)
elif a.delay is not None:
if type(a.delay) == dict:
return 0
else:
return a.delay
else:
return clock_step_delay

background_pool = ThreadPool(0)
new_action_list = []
for a in actions:
delay = get_delay(a)
new_action_list += background_pool.process(a, delay)
return new_action_list

def background_poke_target(cls):
class BackgroundPokeTarget(cls):
def run(self, actions):
actions = process_action_list(actions, self.clock_step_delay)
super().run(actions)
return BackgroundPokeTarget
Loading