Skip to content

Commit eb5afcf

Browse files
authored
Fix Python App Workflow and no_fpga tests (#25) Fixes #22
* Fix calc_impedance_test by increasing test frequency * Allow for no ep_defines path, exception on file not existing * Change all DDR3 parameters to be class attributes Allows DDR3 parameters to be accessed without instantiating DDR3 * Turn "make_..." style methods into staticmethods Allows calling method from the class or an instance * Make DDR3 class attributes separate instead of tuple * Update calc_impedance_test to use DDR3 without instantiation * Attempt to pip install from GitHub branch * Add environment variable to hold github.ref_name context * Make pip install location a string I am hoping this will allow the $BRANCH environment variable to be used * Fix ref_name typo and add echo Echo to display the branch we are installing from (should be the branch the commit is on) * Use github.head_ref instead of github.ref_name
1 parent 9261e7e commit eb5afcf

File tree

4 files changed

+109
-78
lines changed

4 files changed

+109
-78
lines changed

.github/workflows/python-app.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ on:
1111

1212
permissions:
1313
contents: read
14+
15+
env:
16+
BRANCH: ${{ github.head_ref }}
1417

1518
jobs:
1619
build:
@@ -27,7 +30,8 @@ jobs:
2730
run: |
2831
python -m pip install --upgrade pip
2932
pip install flake8 pytest
30-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
33+
echo "Installing from branch: $BRANCH"
34+
pip install "git+https://github.com/Ajstros/pyripherals@$BRANCH"
3135
- name: Lint with flake8
3236
run: |
3337
# stop the build if there are Python syntax errors or undefined names

python/src/pyripherals/core.py

+7
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ def update_endpoints_from_defines(ep_defines_path=configs['ep_defines_path']):
155155
Returns -1 if there is a naming collision in ep_defines.v
156156
"""
157157

158+
# Leave as None if there is no ep_defines.v
159+
if ep_defines_path is None:
160+
warn(f'No ep_defines_path set in your {config_path} file')
161+
return dict()
162+
elif not os.path.exists(ep_defines_path):
163+
raise FileNotFoundError(f'ep_defines_path = {ep_defines_path} not found')
164+
158165
# Get all lines
159166
with open(ep_defines_path, 'r') as file:
160167
lines = file.readlines()

python/src/pyripherals/peripherals/DDR3.py

+54-49
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,29 @@ class DDR3():
5151
5252
"""
5353

54+
BLOCK_SIZE = 2048 # 1/2 the incoming FIFO depth in bytes (size of the BlockPipeIn)
55+
# number of channels that the DDR is striped between (for DACs)
56+
NUM_CHANNELS = 8
57+
UPDATE_PERIOD = 400e-9 # 2.5 MHz -- requires SCLK ~ 50 MHZ
58+
PORT1_INDEX = 0x3_7f_ff_f8
59+
NUM_ADC_CHANNELS = 8 # number of 2 byte chunks in DDR
60+
ADC_PERIOD = 200e-9
61+
62+
# the index is the DDR address that the circular buffer stops at.
63+
# need to write all the way up to this stoping point otherwise the SPI output will glitch
64+
SAMPLE_SIZE = int((PORT1_INDEX + 8)/4)
65+
5466
def __init__(self, fpga, endpoints=None, data_version='TIMESTAMPS'):
5567
if endpoints is None:
5668
endpoints = Endpoint.get_chip_endpoints('DDR3')
5769
self.fpga = fpga
5870
self.endpoints = endpoints
59-
self.parameters = {'BLOCK_SIZE': 2048, # 1/2 the incoming FIFO depth in bytes (size of the BlockPipeIn)
60-
# number of channels that the DDR is striped between (for DACs)
61-
'channels': 8,
62-
'update_period': 400e-9, # 2.5 MHz -- requires SCLK ~ 50 MHZ
63-
'port1_index': 0x3_7f_ff_f8,
64-
'adc_channels': 8, # number of 2 byte chunks in DDR
65-
'adc_period': 200e-9
66-
}
67-
68-
# the index is the DDR address that the circular buffer stops at.
69-
# need to write all the way up to this stoping point otherwise the SPI output will glitch
70-
self.parameters['sample_size'] = int((self.parameters['port1_index'] + 8)/4)
71-
self.parameters['data_version'] = data_version # sets deswizzling mode
71+
self.data_version = data_version # sets deswizzling mode
7272

7373
self.data_arrays = []
74-
for i in range(self.parameters['channels']):
74+
for i in range(DDR3.NUM_CHANNELS):
7575
self.data_arrays.append(np.zeros(
76-
self.parameters['sample_size']).astype(np.uint16))
76+
DDR3.SAMPLE_SIZE).astype(np.uint16))
7777

7878
self.clear_adc_debug()
7979

@@ -97,7 +97,8 @@ def clear_adc_debug(self):
9797
self.fpga.clear_wire_bit(self.endpoints['ADC_DEBUG'].address,
9898
self.endpoints['ADC_DEBUG'].bit_index_low)
9999

100-
def make_flat_voltage(self, amplitude):
100+
@staticmethod
101+
def make_flat_voltage(amplitude):
101102
"""Return a constant unit16 array of value amplitude.
102103
103104
Array length based on the sample_size parameter. The conversion from
@@ -115,11 +116,12 @@ def make_flat_voltage(self, amplitude):
115116
to be assigned to DDR data array
116117
"""
117118

118-
amplitude = np.ones(self.parameters['sample_size'])*amplitude
119+
amplitude = np.ones(DDR3.SAMPLE_SIZE)*amplitude
119120
amplitude = amplitude.astype(np.uint16)
120121
return amplitude
121122

122-
def closest_frequency(self, freq):
123+
@staticmethod
124+
def closest_frequency(freq):
123125
"""Determine closest frequency so the waveform evenly divides into the length of the DDR3
124126
125127
Parameters
@@ -133,22 +135,23 @@ def closest_frequency(self, freq):
133135
The closest possible frequency
134136
"""
135137

136-
samples_per_period = (1/freq) / self.parameters['update_period']
138+
samples_per_period = (1/freq) / DDR3.UPDATE_PERIOD
137139

138140
if samples_per_period <= 2:
139141
print('Frequency is too high for the DDR update rate')
140142
return None
141-
total_periods = self.parameters['sample_size']/samples_per_period
143+
total_periods = DDR3.SAMPLE_SIZE/samples_per_period
142144
# round and recalculate frequency
143145
round_total_periods = np.round(total_periods)
144-
round_samples_per_period = self.parameters['sample_size'] / \
146+
round_samples_per_period = DDR3.SAMPLE_SIZE / \
145147
round_total_periods
146148
new_frequency = 1 / \
147-
(self.parameters['update_period'] * round_samples_per_period)
149+
(DDR3.UPDATE_PERIOD * round_samples_per_period)
148150

149151
return new_frequency
150152

151-
def make_sine_wave(self, amplitude, frequency,
153+
@staticmethod
154+
def make_sine_wave(amplitude, frequency,
152155
offset=0x2000, actual_frequency=True):
153156
"""Return a sine-wave array for writing to DDR.
154157
@@ -179,10 +182,10 @@ def make_sine_wave(self, amplitude, frequency,
179182
print('Error: amplitude in sine-wave is too large')
180183
return -1
181184
if actual_frequency:
182-
frequency = self.closest_frequency(frequency)
185+
frequency = DDR3.closest_frequency(frequency)
183186

184-
t = np.arange(0, self.parameters['update_period']*self.parameters['sample_size'],
185-
self.parameters['update_period'])
187+
t = np.arange(0, DDR3.UPDATE_PERIOD*DDR3.SAMPLE_SIZE,
188+
DDR3.UPDATE_PERIOD)
186189
# print('length of time axis after creation ', len(t))
187190
ddr_seq = (amplitude)*np.sin(t*frequency*2*np.pi) + offset
188191
if any(ddr_seq < 0) or any(ddr_seq > (2**16-1)):
@@ -191,7 +194,8 @@ def make_sine_wave(self, amplitude, frequency,
191194
ddr_seq = ddr_seq.astype(np.uint16)
192195
return ddr_seq, frequency
193196

194-
def make_ramp(self, start, stop, step, actual_length=True):
197+
@staticmethod
198+
def make_ramp(start, stop, step, actual_length=True):
195199
"""Create a ramp signal to write to the DDR.
196200
197201
The conversion from float or int voltage to int digital (binary) code
@@ -217,17 +221,18 @@ def make_ramp(self, start, stop, step, actual_length=True):
217221
len_ramp_seq = len(ramp_seq)
218222
if actual_length:
219223
length = int(
220-
self.parameters['sample_size']/np.round(self.parameters['sample_size']/len_ramp_seq))
224+
DDR3.SAMPLE_SIZE/np.round(DDR3.SAMPLE_SIZE/len_ramp_seq))
221225
stop = start + length*step
222226
ramp_seq = np.arange(start, stop, step)
223-
num_tiles = self.parameters['sample_size']//len(ramp_seq)
224-
extras = self.parameters['sample_size'] % len(ramp_seq)
227+
num_tiles = DDR3.SAMPLE_SIZE//len(ramp_seq)
228+
extras = DDR3.SAMPLE_SIZE % len(ramp_seq)
225229
ddr_seq = np.tile(ramp_seq, num_tiles)
226230
ddr_seq = np.hstack((ddr_seq, ramp_seq[0:extras]))
227231
ddr_seq = ddr_seq.astype(np.uint16)
228232
return ddr_seq
229233

230-
def make_step(self, low, high, length, actual_length=True, duty=50):
234+
@staticmethod
235+
def make_step(low, high, length, actual_length=True, duty=50):
231236
"""Return a step signal (square wave) to write to the DDR.
232237
233238
The conversion from float or int voltage to int digital (binary) code
@@ -254,12 +259,12 @@ def make_step(self, low, high, length, actual_length=True, duty=50):
254259

255260
if actual_length:
256261
length = int(
257-
self.parameters['sample_size']/np.round(self.parameters['sample_size']/length))
262+
DDR3.SAMPLE_SIZE/np.round(DDR3.SAMPLE_SIZE/length))
258263
l_first = int(length/100*duty)
259264
l_end = int(length/100*(100-duty))
260265
ramp_seq = np.concatenate((np.ones(l_first)*low, np.ones(l_end)*high))
261-
num_tiles = self.parameters['sample_size']//len(ramp_seq)
262-
extras = self.parameters['sample_size'] % len(ramp_seq)
266+
num_tiles = DDR3.SAMPLE_SIZE//len(ramp_seq)
267+
extras = DDR3.SAMPLE_SIZE % len(ramp_seq)
263268
ddr_seq = np.tile(ramp_seq, num_tiles)
264269
ddr_seq = np.hstack((ddr_seq, ramp_seq[0:extras]))
265270
ddr_seq = ddr_seq.astype(np.uint16)
@@ -269,10 +274,10 @@ def write_channels(self, set_ddr_read=True):
269274
"""Write the channels as striped data to the DDR."""
270275

271276
data = np.zeros(
272-
int(len(self.data_arrays[0])*self.parameters['channels']))
277+
int(len(self.data_arrays[0])*DDR3.NUM_CHANNELS))
273278
data = data.astype(np.uint16)
274279

275-
for i in range(self.parameters['channels']):
280+
for i in range(DDR3.NUM_CHANNELS):
276281
if i % 2 == 0: # extra order swap on the 32 bit wide pipe
277282
data[(7-i - 1)::8] = self.data_arrays[i]
278283
else:
@@ -305,7 +310,7 @@ def write_buf(self, buf, set_ddr_read=True):
305310
print('Writing to DDR...')
306311
time1 = time.time()
307312
block_pipe_return = self.fpga.xem.WriteToBlockPipeIn(epAddr=self.endpoints['BLOCK_PIPE_IN'].address,
308-
blockSize=self.parameters['BLOCK_SIZE'],
313+
blockSize=DDR3.BLOCK_SIZE,
309314
data=buf)
310315
print(f'The length of the DDR write was {block_pipe_return}')
311316

@@ -514,12 +519,12 @@ def read_adc_block(self, sample_size=None, source='ADC', DEBUG_PRINT=False):
514519
"""
515520

516521
if sample_size is None:
517-
data = np.zeros((self.parameters['sample_size'],), dtype=int)
522+
data = np.zeros((DDR3.SAMPLE_SIZE,), dtype=int)
518523
data_buf = bytearray(data)
519524
else:
520525
data_buf = bytearray(sample_size)
521526

522-
block_size = self.parameters['BLOCK_SIZE']
527+
block_size = DDR3.BLOCK_SIZE
523528
# check block size
524529
if block_size % 16 != 0:
525530
print('Error in read adc. Block size is not a multiple of 16')
@@ -753,16 +758,16 @@ def save_data(self, data_dir, file_name, num_repeats=4, blk_multiples=40, append
753758
else:
754759
file_mode = 'w'
755760

756-
chunk_size = int(self.parameters["BLOCK_SIZE"] * blk_multiples / (
757-
self.parameters['adc_channels']*2)) # readings per ADC
761+
chunk_size = int(DDR3.BLOCK_SIZE * blk_multiples / (
762+
DDR3.NUM_ADC_CHANNELS*2)) # readings per ADC
758763
repeat = 0
759764
adc_readings = chunk_size*num_repeats
760765
print(f'Anticipated chunk size (readings per channel) {chunk_size}')
761766
print(
762-
f'Reading {adc_readings*2/1024} kB per ADC channel for a total of {adc_readings*self.parameters["adc_period"]*1000} ms of data')
767+
f'Reading {adc_readings*2/1024} kB per ADC channel for a total of {adc_readings*DDR3.ADC_PERIOD*1000} ms of data')
763768

764769
self.set_adc_read() # enable data into the ADC reading FIFO
765-
time.sleep(adc_readings*self.parameters['adc_period'])
770+
time.sleep(adc_readings*DDR3.ADC_PERIOD)
766771

767772
# Save ADC DDR data to a file
768773
with h5py.File(full_data_name, file_mode) as file:
@@ -774,8 +779,8 @@ def save_data(self, data_dir, file_name, num_repeats=4, blk_multiples=40, append
774779
# Make space for first round of new data. Not needed when not appending because the data set is created with chunk_size space
775780
data_set.resize(data_set.shape[1] + chunk_size, axis=1)
776781
else:
777-
data_set = file.create_dataset("adc", (self.parameters['adc_channels'], chunk_size), maxshape=(
778-
self.parameters['adc_channels'], None))
782+
data_set = file.create_dataset("adc", (DDR3.NUM_ADC_CHANNELS, chunk_size), maxshape=(
783+
DDR3.NUM_ADC_CHANNELS, None))
779784
data_set.attrs['bitfile_version'] = self.fpga.bitfile_version
780785
new_data_index = 0
781786

@@ -787,11 +792,11 @@ def save_data(self, data_dir, file_name, num_repeats=4, blk_multiples=40, append
787792
elif self.parameters['data_version'] == 'TIMESTAMPS':
788793
chan_data = self.deswizzle(d)
789794

790-
if self.parameters['adc_channels'] == 4:
795+
if DDR3.NUM_ADC_CHANNELS == 4:
791796
chan_stack = np.vstack(
792797
(chan_data[0], chan_data[1], chan_data[2], chan_data[3]))
793798

794-
if self.parameters['adc_channels'] == 8:
799+
if DDR3.NUM_ADC_CHANNELS == 8:
795800
chan_stack = np.vstack((chan_data[0], chan_data[1], chan_data[2], chan_data[3],
796801
chan_data[4], chan_data[5], chan_data[6], chan_data[7]))
797802

@@ -826,7 +831,7 @@ def read_adc(self, blk_multiples=2048):
826831
"""
827832

828833
t, bytes_read_error = self.read_adc_block( # just reads from the block pipe out
829-
sample_size=self.parameters["BLOCK_SIZE"] * blk_multiples
834+
sample_size=DDR3.BLOCK_SIZE * blk_multiples
830835
)
831836
d = np.frombuffer(t, dtype=np.uint8).astype(np.uint32)
832837
print(f'Bytes read: {bytes_read_error}')
@@ -838,7 +843,7 @@ def set_index(self, factor, factor2=None):
838843
This is now fixed to improve timing performance.
839844
"""
840845
print('Set index is no longer used. Index is fixed to: {}'.format(
841-
self.parameters['port1_index']))
846+
DDR3.PORT1_INDEX))
842847

843848
def write_setup(self, data_driven_clock=True):
844849
"""Set up DDR for writing."""

0 commit comments

Comments
 (0)